문자열에서 특수 문자를 이스케이프 처리하는 방법은 무엇입니까?


16

$file파일 이름의 값을 보유 한다고 가정 하십시오 Dr' A.tif. bash 프로그래밍에서 특수 문자를 $file제거하지 않고 작은 따옴표와 다른 특수 문자를 어떻게 벗어날 수 있습니까?

2014 년 7 월 9 일 업데이트

@Gilles에서 요청을 처리 할 수있게하지 않는 코드에 따라 Dr' A.tif:

files=$(find /path/ -maxdepth 1 -name "*.[Pp][Dd][Ff]" -o -name "*.[Tt][Ii][Ff]")
echo "${files}" > ${TEMP_FILE}
while read file
do
   newfile=$(echo "${file}" | sed 's, ,\\ ,g') ## line 1
done < ${TEMP_FILE}

@Patrick on 에서 답을 시도한 후에는 line 1효과가있는 것 같습니다. 하지만이 같은 파일이있는 경우 Dr\^s A.tif, printf명령 도움이하지 않는 것, 그것은 나를 보여줍니다 Dr\^s\ A.tif. 다음과 같이 콘솔에서 수동으로 시도하면 :

printf "%q" "Dr\^s A.tif"

나는이 출력을 가질 것이다 :

Dr\\\^s\ A.tif

이것을 처리하는 방법에 대한 아이디어가 있습니까?


3
어떤 맥락에서 $ file을 사용할 것으로 예상하십니까? 또는이 문제가 특수 문자가있는 문자열을 $ file에 할당합니까?
rob

실제로 find 명령은 파일 목록 배열을 반환합니다. 그런 다음이 파일 목록을 $ file 변수로 반복합니다.
huahsin68

2
여기에 정답이 나와 있지만 실제로 묻는 질문에 대한 답이 아닐 수도 있습니다. 귀하의 의견에 따르면, 귀하가 잘못된 길을 가고 있다고 의심합니다. 코드를 계속 표시하지 않기 때문에 많은 도움을 줄 수 없습니다. 그러나 쉘 스크립트가 공백이나 다른 특수 문자에서 왜 질식합니까? 를 읽는 것이 좋습니다 . 배경으로. 스크립트를 보여주고 원하는 것을 설명하십시오.
Gilles 'SO- 악마 그만해'

답변:


14

printf내장 기능을 사용 %q하여이를 수행 할 수 있습니다 . 예를 들면 다음과 같습니다.

$ file="Dr' A.tif"
$ printf '%q\n' "$file"
Dr\'\ A.tif

$ file=' foo$bar\baz`'
$ printf '%q\n' "$file"
\ foo\$bar\\baz\`

bash 문서에서 printf:

In addition to the standard format specifications described in printf(1)
and printf(3), printf interprets:

 %b       expand backslash escape sequences in the corresponding argument
 %q       quote the argument in a way that can be reused as shell input
 %(fmt)T  output the date-time string resulting from using FMT as a format
          string for strftime(3)

예를 들어 큰 따옴표를 보존해야 할 때와 같은 특정 경우에는 작동하지 않습니다.
user3467349

@ user3467349 따옴표로 잘 작동합니다. 나는 당신이 같은 것을 시도하고 있다는 것을 내기하고 있습니다 printf '%s' "foo". 먼저 쉘에서 인수 구문 분석이 작동하는 방식을 이해해야합니다. gnu.org/software/bash/manual/bash.html#Shell-Operation # 2는 # 6 이전에 발생합니다.를 참조하십시오 .
Patrick

printf다른 조작없이 인쇄 된이 문자열의 예를 제공 할 수 있습니까?It doesn't have a: ""
user3467349

귀하의 문제는와 아무 관련이 없습니다 printf. 문제는 쉘이 문자열을 구문 분석하지 않기를 원한다는 것입니다. 그렇게하려면 입력을 구문 분석하지 않는 방식으로 입력을 쉘에 전달해야합니다. 이를 수행하는 한 가지 방법은 read -r -p 'input: ' && printf '%q\n' "$REPLY"이며 프롬프트가 표시되면 입력을 제공하십시오.
Patrick

1
내가 여러 번 말했듯이. 원시 데이터를 셸에 전달하는 방법을 모르는 것은 문제가 아닙니다 printf. 아마도 문제와 관련이없는 해결책을 비판하기보다는 질문을해야합니다.
Patrick

4

시험:-

file=Dr\'\ A.tif
echo $file
Dr' A.tif

또는

file="Dr' A.tif"
echo $file
Dr' A.tif

또는 문자열에 큰 따옴표가 포함 된 경우 :-

file='Dr" A.tif'
echo $file
Dr" A.tif

인터넷에서 이스케이프 및 인용에 대한 좋은 자습서가 있습니다. 시작 이 하나 .


1

스크립트에서 처리중인 파일 이름을 이스케이프 처리하지 않아도됩니다. 이스케이프는 파일 이름을 스크립트에 리터럴 로 넣거나 여러 파일 이름을 단일 입력 스트림으로 다른 스크립트에 전달 하려는 경우에만 필요합니다 .

당신의 출력을 통해 반복하고 있기 때문에 find, (!) 가장 간단한 방법 중 하나입니다 가능한 모든 경로를 처리 :

while IFS= read -r -d ''
do
    file_namex="$(basename -- "$REPLY"; echo x)"
    file_name="${file_namex%$'\nx'}"
    do_something -- "$file_name"
done <(find "$some_path" -exec printf '%s\0' {} +)


-1

가장 많이 사용되는 답변을 포함하여 이러한 답변 printf "%q"은 추가 조작없이 모든 경우에 작동하지 않습니다. 다음을 제안합니다 (아래 예).

cat <<EOF; 2015-11-07T03:34:41Z app[postgres.0000]: [TAG] text-search query doesn't contain lexemes: "" EOF


n00b 질문을 실례하지만 실제로 이것을 사용하여 문자열의 문자를 이스케이프 처리하는 방법에 대해 자세히 설명 할 수 있습니까? 내 터미널에 작성한 코드를 복사하면 2015-11-07T03 : 34 : 41Z app [postgres.0000] : [TAG] 텍스트 검색 쿼리에 lexemes가 포함되어 있지 않습니다 : ""... 아무것도 이스케이프 처리되지 않습니다. .
SharkAlley

말 그대로 요점입니다. 모든 특수 문자 특별한 의미가 아닌 리터럴 문자로 해석됩니다. 차이점을 보려면 "위의 문자열" 을 에코 하십시오.
user3467349
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.