文字列内の特殊文字をエスケープする方法は?


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からの回答をline 1、私のために動作するようです。しかし、のようなファイルがある場合Dr\^s A.tifprintfコマンドは役に立たないようですDr\^s\ A.tif。次のようにコンソールで手動で試してみると:

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

この出力があります:

Dr\\\^s\ A.tif

これを処理する方法はありますか?


3
どのようなコンテキストで$ fileを使用する予定ですか?または、この問題は特殊文字を含む文字列を$ fileに割り当てますか?
ロブ14

実際、findコマンドはファイルリストの配列を返します。そして、このファイルリストをループして$ file変数に入れます。
huahsin68 14

2
ここでいくつかの正しい答えが与えられましたが、おそらくあなたが本当に求めている質問に対する答えではありません。ここでのコメントから、あなたは間違った方向に進んでいると強く疑います。コードを表示し続けないため、多くのことはできません。ただし、なぜシェルスクリプトが空白やその他の特殊文字でチョークするのかを読むことをお勧めします背景として。スクリプトを見せて、何をしたいのか説明してください。
ジル 'SO-悪であるのをやめる' 14

回答:


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の前に起こります。
パトリック

printf他の操作なしで印刷されたこの文字列の例を提供してIt doesn't have a: ""
いただけますか-user3467349

あなたの問題はに関係ありませんprintf。問題は、シェルが文字列を解析したくないことです。そのためには、シェルに入力を渡さなければなりません。シェルはそれを解析しようとさえしません。これを行う1つの方法はread -r -p 'input: ' && printf '%q\n' "$REPLY"、プロンプトが表示されたときに入力を提供することです。
パトリック

1
今何度か言ったように。生データをシェルに渡す方法を知らなくても問題ありませんprintf。おそらく、問題とは関係のない解決策を批判するのではなく、質問をする必要があります。
パトリック

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


1

スクリプトで処理しているファイル名をエスケープする必要はありません。エスケープは、ファイル名をリテラルとしてスクリプトに入れる場合、または複数のファイル名を単一の入力ストリームとして別のスクリプトに渡す場合にのみ必要です。

の出力をループしているのでfindこれ可能なすべてのパス処理する最も簡単な方法(!)の1つです。

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] text-search query does not include lexemes: "" ...何もエスケープされません。
SharkAlley

それが文字通りポイントです。すべての特殊文字、特別な意味ではなくリテラル文字として解釈されます。代わりに「上記の文字列」をエコーして、違いを確認してください。
-user3467349
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.