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

$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} 

line 1の@Patrick からの回答は、私にとってはうまくいくようです。しかし、Dr\^s A.tifprintfコマンドは役に立たないようです。Dr\^s\ A.tifと表示されます。次のようにコンソールで手動で試してみると:

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

次の出力が表示されます:

Dr\\\^s\ A.tif

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

コメント

  • 何でコンテキスト$ fileを使用する予定ですか?または、この問題は特殊文字を含む文字列を$ fileに割り当てるのですか?
  • 実際、findコマンドはファイルリストの配列を返します。次に、このファイルリストをループして$ file変数に入れます。
  • 'ここで正しい答えがいくつか与えられていますが、おそらくそれらは答えではありません。 'が本当に尋ねている質問。ここでのコメントから、あなたは'間違った方向に進んでいるのではないかと強く疑っています。 'コードを表示し続けないため、あまり役に立ちません。ただし、シェルスクリプトが空白やその他の特殊文字でチョークするのはなぜですか?を背景として読むことをお勧めします。 スクリプトを表示して、やりたいことを説明します。

回答

あなたこれを実現するには、%qに組み込まれているprintfを使用できます。例:

$ file="Dr" A.tif" $ printf "%q\n" "$file" Dr\"\ A.tif $ file=" foo$bar\baz`" $ printf "%q\n" "$file" \ foo\$bar\\baz\` 

printfのbashドキュメントから:

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) 

コメント

  • これ'特定のケースでは機能しません。eg二重引用符を保持する必要がある場合。
  • @ user3467349引用符で問題なく機能します。 'あなたに賭けています' printf '%s' "foo"のようなものを試しています。最初に、シェルで引数の解析がどのように機能するかを理解する必要があります。 gnu.org/software/bash/manual/bash.html#Shell-Operation #2は#6の前に発生します。
  • よろしいですか? printfで出力され、他の操作は行われないこの文字列の例を提供してくださいIt doesn't have a: ""
  • 問題は何の関係もありませんprintf。あなたの問題は、シェルに文字列を解析させたくないということです。'そのためには、'解析しようとさえしない方法で入力をシェルに渡す必要があります。これを行う1つの方法は、read -r -p 'input: ' && printf '%q\n' "$REPLY"であり、プロンプトが表示されたら入力を提供します。
  • 'が言ったように今数回。生データをシェルに渡す方法がわからないことは、' printfの問題ではありません。おそらく、問題とは関係のない解決策を批評するのではなく、質問する必要があります。

回答

試してみてください:-

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

または

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

または、文字列にdoubleが含まれている場合引用:-

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

ネット上でのエスケープと引用に関する優れたチュートリアルがあります。 これから始めます。

回答

「スクリプトで処理しているファイル名をエスケープする必要はありません。エスケープする必要があるのは、ファイル名をリテラルとしてスクリプトに挿入する場合、または複数のファイル名を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" {} +) 

回答

迅速で(非常に)汚い

find . | sed "s/^/"/" | sed "s/$/"/" 

回答

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 ' tが出力されます。 語彙素を含む:" " …何もエスケープされません。
  • その'は文字通り重要であり、すべての特殊文字は 特別な意味ではなく、文字通りの文字として解釈されます。 違いを確認する代わりに、 echo "上記の文字列"を試してください。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です