Bash でエスケープする必要がある文字の包括的なリストはありますか? だけで確認できますsed
か?
特に、%
エスケープする必要があるかどうかを確認していました。私は試した
echo "h%h" | sed 's/%/i/g'
エスケープせずにうまくいき%
ました。%
エスケープする必要がないということですか?必要性を確認する良い方法でしたか?
shell
そしてより一般的には、エスケープするのと同じ文字bash
ですか?
Bash でエスケープする必要がある文字の包括的なリストはありますか? だけで確認できますsed
か?
特に、%
エスケープする必要があるかどうかを確認していました。私は試した
echo "h%h" | sed 's/%/i/g'
エスケープせずにうまくいき%
ました。%
エスケープする必要がないということですか?必要性を確認する良い方法でしたか?
shell
そしてより一般的には、エスケープするのと同じ文字bash
ですか?
sh
だけでなく、 にも機能する 2 つの簡単で安全なルールがありbash
ます。
これは、一重引用符自体を除くすべての文字で機能します。一重引用符をエスケープするには、その前の引用符を閉じ、一重引用符を挿入してから、引用符を再度開きます。
'I'\''m a s@fe $tring which ends in newline
'
コマンド:sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"
これは、改行を除くすべての文字で機能します。改行文字には、一重引用符または二重引用符を使用します。空の文字列は引き続き処理する必要があります - に置き換えます""
\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/$/"/'
.
のような簡単に安全な文字セットがあり、[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 仕様を読むことで簡単に検証できます。bash については、@AustinPhillips がリンクしているリファレンス マニュアルsh
を確認してください)
${var@Q}
bash では、Parameter ExpansionのParameter transformation@
コマンドを使用して、変数の内容を保存できます。
${parameter@operator} Parameter transformation. The expansion is either a transforma‐ tion of the value of parameter or information about parameter itself, depending on the value of operator. Each operator is a single letter: Q The expansion is a string that is the value of parameter quoted in a format that can be reused as input. ... A The expansion is a string in the form of an assignment statement or declare command that, if evaluated, will recreate parameter with its attributes and value.
サンプル:
$ var=$'Hello\nGood world.\n'
$ echo "$var"
Hello
Good world.
$ echo "${var@Q}"
$'Hello\nGood world.\n'
$ echo "${var@A}"
var=$'Hello\nGood world.\n'
この種のリクエスト用に構築された特別な printf
フォーマット ディレクティブ ( ) があります。%q
printf [-v 変数] フォーマット [引数]
%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 から 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 進値、2 番目のフィールドはE
文字をエスケープする必要がある場合、3 番目のフィールドは文字のエスケープされた表現を示します。
,
ですか?、 、 など、必ずしもエスケープする必要のない文字が表示される場合があります。,
}
{
だからいつもではなく、いつか:
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
他の誰かが RTFM を使用する必要がないようにするには... bashで:
文字を二重引用符で囲むと
$
、引用符内のすべての文字のリテラル値が保持されます。`
\
!
...したがって、それら (およびもちろん引用自体) をエスケープしても、おそらく問題ありません。
より保守的な「疑わしい場合はエスケープする」アプローチを取る場合は、識別子文字 (つまり、ASCII 文字、数字、または「_」) をエスケープしないことで、代わりに特別な意味を持つ文字を取得することを回避できるはずです。これらが (つまり、いくつかの奇妙な POSIX 風のシェルで) 特別な意味を持ち、したがってエスケープする必要があることはほとんどありません。
Bourne または POSIX シェルでは、エスケープが必要な文字が Bash とは異なります。一般に、(非常に) Bash はこれらのシェルのスーパーセットであるため、エスケープするものはすべてshell
Bash でエスケープする必要があります。
良い一般的なルールは、「疑わしい場合は回避する」ことです。ただし、一部の文字をエスケープすると、 のような特別な意味が得られます\n
。これらは、およびのman bash
下のページにリストされています。Quoting
echo
それ以外は、英数字以外の文字をエスケープする方が安全です。私は単一の決定的なリストを知りません。
マニュアルページには、それらすべてがどこかにリストされていますが、1 か所にリストされているわけではありません。言語を学ぶ、それが確実な方法です。
私を捕まえたのは!
. これは、Bash (および csh) の特殊文字 (履歴拡張) ですが、Korn シェルにはありません。問題さえecho "Hello world!"
与えます。いつものように一重引用符を使用すると、特別な意味が取り除かれます。
オートコンプリートを使用すると、bash が一部の文字を自動的にエスケープすることに気付きました。
たとえば、 という名前のディレクトリがある場合dir:A
、bash は次のようにオートコンプリートします。dir\:A
これを使用して、ASCII テーブルの文字を使用していくつかの実験を実行し、次のリストを導き出しました。
オートコンプリートで bash エスケープする文字: (スペースを含む)
!"$&'()*,:;<=>?@[\]^`{|}
bash がエスケープしない文字:
#%+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~
/
(ディレクトリ名に使用できないため、除外しました)