Bash를 사용할 때 어떤 문자를 이스케이프해야합니까?
Bash에서 이스케이프해야하는 포괄적 인 문자 목록이 있습니까? 그냥 확인할 수 있습니까 sed
?
특히 %
탈출 해야하는지 여부를 확인하고있었습니다 . 나는 시도했다
echo "h%h" | sed 's/%/i/g'
탈출하지 않고 잘 작동했습니다 %
. %
탈출 할 필요가 없다는 의미 입니까? 이것이 필요성을 점검하는 좋은 방법 이었습니까?
그리고 더 일반적인 : 그들은 탈출하기 위해 동일한 문자입니다 shell
및 bash
?
쉽고 안전한 두 가지 규칙이 sh
있습니다 bash
.
1. 전체 문자열을 작은 따옴표로 묶습니다.
작은 따옴표 자체를 제외한 모든 문자에 적용됩니다. 작은 따옴표를 이스케이프하려면 따옴표를 닫고 작은 따옴표를 삽입 한 후 따옴표를 다시여십시오.
'I'\''m a s@fe $tring which ends in newline
'
sed 명령 : sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"
2. 백 슬래시로 모든 문자를 이스케이프
이것은 개행을 제외한 모든 문자에 적용됩니다. 줄 바꿈 문자의 경우 작은 따옴표 나 큰 따옴표를 사용하십시오. 빈 문자열은 여전히 처리해야합니다.""
\I\'\m\ \a\ \s\@\f\e\ \$\t\r\i\n\g\ \w\h\i\c\h\ \e\n\d\s\ \i\n\ \n\e\w\l\i\n\e"
"
sed 명령 : sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.
2b. 더 읽기 쉬운 버전 2
와 같은 쉽고 안전한 문자 집합 [a-zA-Z0-9,._+:@%/-]
이 있습니다.
I\'m\ a\ s@fe\ \$tring\ which\ ends\ in\ newline"
"
sed 명령 : LC_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.
sed 프로그램에서는 마지막 입력 행이 줄 바꿈 바이트로 끝나는 지 여부를 알 수 없습니다 (빈 경우 제외). 그래서 위의 sed 명령이 그렇지 않다고 가정합니다. 인용 된 줄 바꿈을 수동으로 추가 할 수 있습니다.
쉘 변수는 POSIX 의미의 텍스트에 대해서만 정의됩니다. 이진 데이터 처리가 정의되지 않았습니다. 중요한 구현의 경우 바이너리는 NUL 바이트를 제외하고 작동합니다 (변수는 C 문자열로 구현되고 C 문자열, 즉 프로그램 인수로 사용되기 때문). latin1과 같은 "이진"로케일로 전환해야합니다 .
(의 POSIX 사양을 읽으면 규칙을 쉽게 확인할 수 있습니다 sh
. bash의 경우 @AustinPhillips가 링크 한 참조 매뉴얼을 확인하십시오)
쉘 입력으로 재사용 할 수있는 형식
이 특별 printf
형식 지시자 ( %q
요청 이런 종류의 내장은) :
printf [-v var] 형식 [인수]
%q causes printf to output the corresponding argument in a format that can be reused as shell input.
일부 샘플 :
read foo
Hello world
printf "%q\n" "$foo"
Hello\ world
printf "%q\n" $'Hello world!\n'
$'Hello world!\n'
변수를 통해서도 사용할 수 있습니다 :
printf -v var "%q" "$foo
"
echo "$var"
$'Hello world\n'
모든 (128) ASCII 바이트로 빠른 검사 :
128에서 255까지의 모든 바이트를 이스케이프해야합니다.
for i in {0..127} ;do
printf -v var \\%o $i
printf -v var $var
printf -v res "%q" "$var"
esc=E
[ "$var" = "$res" ] && esc=-
printf "%02X %s %-7s\n" $i $esc "$res"
done |
column
이것은 다음과 같이 렌더링해야합니다.
00 E '' 1A E $'\032' 34 - 4 4E - N 68 - h
01 E $'\001' 1B E $'\E' 35 - 5 4F - O 69 - i
02 E $'\002' 1C E $'\034' 36 - 6 50 - P 6A - j
03 E $'\003' 1D E $'\035' 37 - 7 51 - Q 6B - k
04 E $'\004' 1E E $'\036' 38 - 8 52 - R 6C - l
05 E $'\005' 1F E $'\037' 39 - 9 53 - S 6D - m
06 E $'\006' 20 E \ 3A - : 54 - T 6E - n
07 E $'\a' 21 E \! 3B E \; 55 - U 6F - o
08 E $'\b' 22 E \" 3C E \< 56 - V 70 - p
09 E $'\t' 23 E \# 3D - = 57 - W 71 - q
0A E $'\n' 24 E \$ 3E E \> 58 - X 72 - r
0B E $'\v' 25 - % 3F E \? 59 - Y 73 - s
0C E $'\f' 26 E \& 40 - @ 5A - Z 74 - t
0D E $'\r' 27 E \' 41 - A 5B E \[ 75 - u
0E E $'\016' 28 E \( 42 - B 5C E \\ 76 - v
0F E $'\017' 29 E \) 43 - C 5D E \] 77 - w
10 E $'\020' 2A E \* 44 - D 5E E \^ 78 - x
11 E $'\021' 2B - + 45 - E 5F - _ 79 - y
12 E $'\022' 2C E \, 46 - F 60 E \` 7A - z
13 E $'\023' 2D - - 47 - G 61 - a 7B E \{
14 E $'\024' 2E - . 48 - H 62 - b 7C E \|
15 E $'\025' 2F - / 49 - I 63 - c 7D E \}
16 E $'\026' 30 - 0 4A - J 64 - d 7E E \~
17 E $'\027' 31 - 1 4B - K 65 - e 7F E $'\177'
18 E $'\030' 32 - 2 4C - L 66 - f
19 E $'\031' 33 - 3 4D - M 67 - g
첫 번째 필드가 바이트의 16 진수 값인 E
경우 두 번째는 문자를 이스케이프해야하는 경우 포함 하고 세 번째 필드는 이스케이프 된 문자 표시를 표시합니다.
왜 ,
?
당신은하지 않는 일부 문자를 볼 수 항상 같은 이스케이프 할 필요를 ,
, }
하고 {
.
그래서하지 항상 하지만 언젠가 :
echo test 1, 2, 3 and 4,5.
test 1, 2, 3 and 4,5.
또는
echo test { 1, 2, 3 }
test { 1, 2, 3 }
그러나주의 :
echo test{1,2,3}
test1 test2 test3
echo test\ {1,2,3}
test 1 test 2 test 3
echo test\ {\ 1,\ 2,\ 3\ }
test 1 test 2 test 3
echo test\ {\ 1\,\ 2,\ 3\ }
test 1, 2 test 3
bash 에서 다른 사람이 RTFM을 갖지 못하게하려면 :
큰 따옴표 문자를 묶는 것은 제외하고, 따옴표 내의 모든 문자의 리터럴 값을 보존
$
,`
,\
,와, 역사 확장을 사용하는 경우,!
.
...so if you escape those (and the quote itself, of course) you're probably okay.
If you take a more conservative 'when in doubt, escape it' approach, it should be possible to avoid getting instead characters with special meaning by not escaping identifier characters (i.e. ASCII letters, numbers, or '_'). It's very unlikely these would ever (i.e. in some weird POSIX-ish shell) have special meaning and thus need to be escaped.
Using the print '%q'
technique, we can run a loop to find out which characters are special:
#!/bin/bash
special=$'`!@#$%^&*()-_+={}|[]\\;\':",.<>?/ '
for ((i=0; i < ${#special}; i++)); do
char="${special:i:1}"
printf -v q_char '%q' "$char"
if [[ "$char" != "$q_char" ]]; then
printf 'Yes - character %s needs to be escaped\n' "$char"
else
printf 'No - character %s does not need to be escaped\n' "$char"
fi
done | sort
It gives this output:
No, character % does not need to be escaped
No, character + does not need to be escaped
No, character - does not need to be escaped
No, character . does not need to be escaped
No, character / does not need to be escaped
No, character : does not need to be escaped
No, character = does not need to be escaped
No, character @ does not need to be escaped
No, character _ does not need to be escaped
Yes, character needs to be escaped
Yes, character ! needs to be escaped
Yes, character " needs to be escaped
Yes, character # needs to be escaped
Yes, character $ needs to be escaped
Yes, character & needs to be escaped
Yes, character ' needs to be escaped
Yes, character ( needs to be escaped
Yes, character ) needs to be escaped
Yes, character * needs to be escaped
Yes, character , needs to be escaped
Yes, character ; needs to be escaped
Yes, character < needs to be escaped
Yes, character > needs to be escaped
Yes, character ? needs to be escaped
Yes, character [ needs to be escaped
Yes, character \ needs to be escaped
Yes, character ] needs to be escaped
Yes, character ^ needs to be escaped
Yes, character ` needs to be escaped
Yes, character { needs to be escaped
Yes, character | needs to be escaped
Yes, character } needs to be escaped
Some of the results, like ,
look a little suspicious. Would be interesting to get @CharlesDuffy's inputs on this.
Characters that need escaping are different in Bourne or POSIX shell than Bash. Generally (very) Bash is a superset of those shells, so anything you escape in shell
should be escaped in Bash.
A nice general rule would be "if in doubt, escape it". But escaping some characters gives them a special meaning, like \n
. These are listed in the man bash
pages under Quoting
and echo
.
Other than that, escape any character that is not alphanumeric, it is safer. I don't know of a single definitive list.
The man pages list them all somewhere, but not in one place. Learn the language, that is the way to be sure.
One that has caught me out is !
. This is a special character (history expansion) in Bash (and csh) but not in Korn shell. Even echo "Hello world!"
gives problems. Using single-quotes, as usual, removes the special meaning.
I presume that you're talking about bash strings. There are different types of strings which have a different set of requirements for escaping. eg. Single quotes strings are different from double quoted strings.
The best reference is the Quoting section of the bash manual.
It explains which characters needs escaping. Note that some characters may need escaping depending on which options are enabled such as history expansion.
I noticed that bash automatically escapes some characters when using auto-complete.
For example, if you have a directory named dir:A
, bash will auto-complete to dir\:A
Using this, I runned some experiments using characters of the ASCII table and derived the following lists:
Characters that bash escapes on auto-complete: (includes space)
!"$&'()*,:;<=>?@[\]^`{|}
Characters that bash does not escape:
#%+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~
(I excluded /
, as it cannot be used in directory names)
참고URL : https://stackoverflow.com/questions/15783701/which-characters-need-to-be-escaped-when-using-bash
'development' 카테고리의 다른 글
MVC와 Razor의 Html.TextboxFor와 Html.EditorFor의 차이점 (0) | 2020.05.31 |
---|---|
배경 이미지 CSS를 늘리시겠습니까? (0) | 2020.05.31 |
JavaScript에서 해시 또는 사전 객체를 만드는 방법 (0) | 2020.05.31 |
다시 누를 때 두 번째 활동에서 첫 번째 활동으로 데이터를 전달하는 방법은 무엇입니까? (0) | 2020.05.31 |
팬더 리 샘플 문서 (0) | 2020.05.31 |