$IFS
印刷できない文字(改行文字など)を含めることができる変数の値を表示したいと思います。
これを行うには、次のコマンドを使用します。
echo -n "$IFS" | hexdump -C
これは私にとってうまくいきます。
しかし、このコマンドを使用するのに問題がありますか?たとえば、echo
印刷できない文字を印刷する前に他の文字に置き換えますか?stdout
それとも同様の問題がありますか?
答え1
文字列を視覚的に表現するいくつかの異なる方法:
POSIX
$ printf %s "$IFS" | od -vtc -to1
0000000 \t \n \0
040 011 012 000
0000004
$ printf '%s\n' "$IFS" | LC_ALL=C sed -n l
\t$
\000$
(追加のコンテンツが\n
必要です。そうしないと、sed
最後の行が改行文字で終わらない限り動作は指定されません。)POSIXには、私のzshのようにNULはありませんsh
。入力に NUL が含まれている場合、動作は指定されません。$IFS
sed
シェル組み込み関数
typeset -p
(ksh、zsh、bash、yash)は特定の文字列の明示的な出力を提供できます。$ ksh93 -c 'typeset -p IFS' IFS=$' \t\n' $ zsh -c 'typeset -p IFS' typeset IFS=$' \t\n\C-@' $ mksh -c 'typeset -p IFS' typeset IFS=$' \t\n' $ a=$'\u00e9e\u301\u200b' ksh -c 'typeset -p a' typeset -x a=$'\u[e9]e\u[301]\u[200b]'
ただし、後者(鋭角アクセントと幅0の空白文字を結合するためにUnicodeを使用する場合)の場合、zsh / mkshは役に立ちません(にもかかわらず
LC_ALL=C typeset -p a
)mksh -o utf8-mode
。bash
端末に送信されると、出力は通常明確ではありません。printf %q
printf
GNUprintf
の組み込み機能を使用しksh93
て、次の操作を行いますzsh
。bash
$ a=$'\u00e9e\u301\u200b' bash -c 'printf "%q\n" "$IFS" "$a" ""' $' \t\n' éé '' $ a=$'\u00e9e\u301\u200b' ksh -c 'printf "%q\n" "$IFS" "$a" ""' $' \t\n' $'\u[e9]e\u[301]\u[200b]' '' \ $'\t'$'\n'$'\0' éé '' $ a=$'\u00e9e\u301\u200b' sh -c '/usr/bin/printf "%q\n" "$IFS" "$a" ""' ' '$'\t\n' éé '' $ a=$'\u00e9e\u301\u200b' zsh -c 'LC_ALL=C printf "%q\n" "$IFS" "$a" ""' \ $'\t'$'\n'$'\0' $'\303'$'\251'e$'\314'$'\201'$'\342'$'\200'$'\213' '' $ a=$'\u00e9e\u301\u200b' bash -c 'LC_ALL=C printf "%q\n" "$IFS" "$a" ""' $' \t\n' $'\303\251e\314\201\342\200\213' ''
q
、、qq
のパラメータ拡張フラグqqq
。qqqq
zsh
さまざまな種類の参照については
qqqq
次のとおりです$'...'
。$ a=$'\u00e9e\u301\u200b' zsh -c 'print -r -- ${(qqqq)a}' $'éé' $ a=$'\u00e9e\u301\u200b' zsh -c '(){local LC_ALL=C; print -r -- ${(qqqq)a}}' $'\303\251e\314\201\342\200\213'
次への参照のみを使用してください
q
。q+
必要はい(Unicodeに関する警告はまだ存在しますが)。
さまざまな非標準コマンド:
hex-dumper:
hexdump
、、、...供給する出力(またはksh / zshを使用するか...hd
を使用)。xxd
printf %s "$var"
print -rn -- "$var"
echo -nE - "$var"
zsh
cat -vte
またはcat -A
uconv -x hex
文字のUnicodeコードポイント(エンコードされたバイトの16進値ではない)の場合は、UTF-8でのみ機能します(入力は前処理できますが、iconv -t utf-8
ロケールエンコーディングで有効なテキストである場合のみ)。uconv -x name
役割名の場合recode ..dump
。 16進数と名前ですが、少数のUnicode文字を理解しています(最新バージョンのUnicodeに更新されていません)。ただし、UTF-8以外のロケールでは機能します。
答え2
特に場合はIFS
必ず引用したいか、そうでなければ役に立たなくなります。もうやったので問題ありません。
の場合はecho
場合によって異なります。一部のバージョンはecho
デフォルトでバックスラッシュエスケープを処理しますが、一部はそうではありません。 Bashはそうではありませんが、zshは次のことを行います。
$ bash -c 'echo "foo\nbar"'
foo\nbar
$ zsh -c 'echo "foo\nbar"'
foo
bar
使用する方が良いですprintf
:printf "%s" "$IFS" | hexdump -C
。
また見なさい:なぜprintfがechoより優れているのですか?
printf "%q" "$IFS"
Bashとzshでも動作します。
\0
これは、BashがNULバイト()をまったく処理できないのに対し、zshは処理できることを除いて良い状態を維持する必要があります。大きな打撃:
$ var=$'foo\0bar'
$ printf "%q\n" "$var"
foo
ジシュ語:
$ var=$'foo\0bar'
$ printf "%q\n" "$var"
foo$'\0'bar
答え3
Bashで動作しない唯一の文字はnullです。
$ var="$(perl -wE 'print map chr, 0 .. 255')"
$ echo -n "$var" | xxd
0000000: 0102 0304 0506 0708 090a 0b0c 0d0e 0f10 ................
0000010: 1112 1314 1516 1718 191a 1b1c 1d1e 1f20 ...............
0000020: 2122 2324 2526 2728 292a 2b2c 2d2e 2f30 !"#$%&'()*+,-./0
0000030: 3132 3334 3536 3738 393a 3b3c 3d3e 3f40 123456789:;<=>?@
0000040: 4142 4344 4546 4748 494a 4b4c 4d4e 4f50 ABCDEFGHIJKLMNOP
0000050: 5152 5354 5556 5758 595a 5b5c 5d5e 5f60 QRSTUVWXYZ[\]^_`
0000060: 6162 6364 6566 6768 696a 6b6c 6d6e 6f70 abcdefghijklmnop
0000070: 7172 7374 7576 7778 797a 7b7c 7d7e 7f80 qrstuvwxyz{|}~..
0000080: 8182 8384 8586 8788 898a 8b8c 8d8e 8f90 ................
0000090: 9192 9394 9596 9798 999a 9b9c 9d9e 9fa0 ................
00000a0: a1a2 a3a4 a5a6 a7a8 a9aa abac adae afb0 ................
00000b0: b1b2 b3b4 b5b6 b7b8 b9ba bbbc bdbe bfc0 ................
00000c0: c1c2 c3c4 c5c6 c7c8 c9ca cbcc cdce cfd0 ................
00000d0: d1d2 d3d4 d5d6 d7d8 d9da dbdc ddde dfe0 ................
00000e0: e1e2 e3e4 e5e6 e7e8 e9ea ebec edee eff0 ................
00000f0: f1f2 f3f4 f5f6 f7f8 f9fa fbfc fdfe ff ...............
printf
移植性は優れてecho
いますが、私のシステムとシェルでは出力はまったく同じです。
printf %s "$var"
答え4
私はQ
Bashのパラメータ変換演算子が好きです:
echo "${IFS@Q}"
出力:
$' \t\n'
この$'string'
参照はANSI-Cの引用。
このQ
演算子は、SSHを介してコマンドに引数を渡すためにも使用できます。
f='filename with space'
ssh "$host" "ls -l ${f@Q}"
これパラメータ拡張セクションにはすべての演算子のリストが含まれています。このA
演算子も便利です。
a=(array with 'various elements')
echo "${a[@]@A}"
出力:
declare -a a=([0]="array" [1]="with" [2]="various elements")