web-dev-qa-db-ja.com

印刷できない文字を含む変数を印刷する方法は?

$IFS変数の値を表示したいのですが、これには印刷できない文字が含まれている可能性があります(例:改行)。

そのために次のコマンドを使用しました。

echo -n "$IFS" | hexdump -C

私の場合、それはうまくいきました。

しかし、このコマンドの使用に何か問題がありますか?たとえば、echostdoutに出力する前に、印刷できない文字を他の文字に置き換えますか、それとも他の問題がありますか?

8
user270971

特に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

参照: echoよりprintfが優れている理由

printf "%q" "$IFS"はBashとzshでも動作します。

これは、BashがNULバイト(\0)まったく、zshはできます。バッシュ:

$ var=$'foo\0bar'
$ printf "%q\n" "$var"
foo

zsh:

$ var=$'foo\0bar'
$ printf "%q\n" "$var"
foo$'\0'bar
6
ilkkachu

文字列の視覚的表現を与える際のいくつかのさまざまなアプローチ:

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$

(最後の行が改行で終わっていない場合のsedの動作は指定されていないため、追加の\nが必要です)。 POSIX shは、私のzshがここで行うように、$IFSにNULがありません。入力にNULが含まれている場合の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]'
    

    しかし、後者(急性アクセントとゼロ幅スペース文字を組み合わせたUnicodeを使用)の場合、zsh/mkshは役に立ちません(LC_ALL=C typeset -p amksh -o utf8-modeを併用しても)。 bashの出力は、通常、端末に送信したときに明確になります。

  • printf %q with GNU printf and printf builtin ksh93zsh and 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内のqqqqqqqqqzshパラメータ展開フラグ。

    さまざまなタイプの引用について、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'
    

    qq+もあり、それはneedであるものに対してのみ引用符を使用します(ただし、これらのunicodeのものにはまだ注意が必要です)。

さまざまな非標準コマンド:

  • hex-dumper:hexdumphdxxd... printf %s "$var"(またはprint -rn -- "$var"の出力をフィードしますksh/zsh、またはecho -nE - "$var" with 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以外のロケールで動作します。

4

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    ...............

printfechoよりも移植性がありますが、私のシステムとシェル(bash)の場合、出力はまったく同じです。

printf %s "$var"
1
choroba