web-dev-qa-db-ja.com

bashコマンド文字列の逐語的な文字を確認するにはどうすればよいですか?

私は今朝bashターミナルでこの奇妙な振る舞いをしました:

user@home:/home/user$ [ -f /etc/openvpn/client.conf ] && echo true
bash: [: missing «]»
user@home:/home/user$ [ -f /etc/openvpn/client.conf ] && echo true
true
  • 最初のコマンドは、geditで編集されたスクリプトからのpastedでした。
  • 2番目は、ターミナルで直接入力されました。

掘り下げた後、30番目の文字(client.confと "]"の間のスペース)を削除し、それをスペースに置き換えると、コマンドが再び動作します。

私の仮定は正しかった:不明な空白文字がコマンドに入力されましたが、質問は次のとおりです:

  1. コマンドをデバッグできるように、ターミナルでこれらの文字を表示するにはどうすればよいですか?そしてもっと重要なこと:
  2. これが再発しないようにするにはどうすればよいですか?

ところで、私はUbuntu 18.04 /フランス語を実行しています。コマンドを貼り付けるスクリプトはUSBドライブにあり、Windowsでも編集されている可能性があります。


非常に良い答えをありがとう。悪い文字はc2 a0の改行なしスペースUTF-8文字です。質問 sedで特殊な「M-BM-」文字を削除する方法 には、その文字について興味深い事実があります。

奇妙なことに、スクリプトにはこのキャラクターが含まれていません。どこから来たのかわかりません。

15
Gabriel Glenn

1つのオプションは、16進ビューアまたはエディタで使用しようとしている文字を確認することです。 hexdumpは、端末に制限がある場合に適したオプションです。

$ hexdump -Cv <<"EOF"
> [ -f /etc/openvpn/client.conf ] && echo true
> EOF
00000000  5b 20 2d 66 20 2f 65 74  63 2f 6f 70 65 6e 76 70  |[ -f /etc/openvp|
00000010  6e 2f 63 6c 69 65 6e 74  2e 63 6f 6e 66 20 5d 20  |n/client.conf ] |
00000020  26 26 20 65 63 68 6f 20  74 72 75 65 0a           |&& echo true.|
0000002d

spaceclose-square-bracespaceが正しいことがわかります-0x200x5D0x20

これらの値はASCIIコード、 16進数 で表示されます。範囲外の値0x20-0x7E"ではありません印刷可能な文字 " ASCIIに関する限り、コマンドラインインターフェイスではうまく機能しない可能性があります。

注:最初の "broken"行を上記のhexdumpの例で使用するためにコピーしたので、何かがnot-an-ASCII-spaceをASCII元のソースとレンダリングされた質問の間のスペースに置き換えました。


これを繰り返すには、次の手順を実行します。

  1. hexdump -Cv <<"EOF"と入力して押します Enter
  2. 使用したいテキストを貼り付けます
  3. 1行にEOFと入力し、 Enter

ターミナルとコマンドラインインターフェイスは、特殊文字を適切に処理しません-ご存じのとおりです。ドキュメントのフォーマットに細心の注意を払っていない場合は、Microsoft Word(およびその他)で「smart quotes」、em-dashesを使用すると問題が発生します。リストは続きます。 ..

違いを見つけます:(上部は「smart quotes」、下部は「straight quotes」)

example of smart quotes vs straight quotes

$ hexdump -Cv <<"EOF"
> “quoted string”
> EOF
00000000  e2 80 9c 71 75 6f 74 65  64 20 73 74 72 69 6e 67  |...quoted string|
00000010  e2 80 9d 0a                                       |....|
00000014

ここで、開いた引用は単純なASCII引用(")ではありませんが、Unicode/ TF-8 シリーズ-0xE2です、0x800x9C、または U+201C -予想どおりに端末が処理しません。

Kiwyのcat -Aの提案も機能します。

$ cat -A <<"EOF"
> “quoted string”
> EOF
M-bM-^@M-^\quoted stringM-bM-^@M-^]$

注:echo "..." | hdを使用すると、bashが検査しようとしているストリング。これは、スクリプトのコンポーネントを検査しようとするときに特に懸念されます。

たとえば、次のことを試してください。

$ echo "${USER}"
attie

$ echo "`whoami`"
attie

$ echo "$(whoami)"
attie

$ cat <<EOF
> ${USER}
> EOF
attie

これらのメソッドは、コンポーネントを関連するテキストに置き換えています。これを回避するには、次のいずれかの方法を使用します。単一引用符(')と "quoted heredoc""EOF")の使用に注意してください。

$ echo '${USER}'
${USER}

$ echo '`whoami`'
`whoami`

$ echo '$(whoami)'
$(whoami)

$ cat <<"EOF"
> ${USER}
> EOF
${USER}
11
Attie

cat-Aオプション:マニュアルから:

   -A, --show-all
          equivalent to -vET
   -E, --show-ends
          display $ at end of each line
   -T, --show-tabs
          display TAB characters as ^I
   -v, --show-nonprinting
          use ^ and M- notation, except for LFD and TAB

そう cat -A yourscrip.shは、目に見えない奇妙な文字を表示します。

18
Kiwy

echo "<your command>" | hdは動作するはずです。バックスペース(0x08)またはコード> = 80の文字を探します。 echo "<your command>" | wc -bとカウントがあなたが見るものと一致することをチェックすることも良い考えです。

名前に「Office」が付いているものから作成されたファイルからのものをコピーすることは危険です。そのようなソフトウェアは文字を置き換えるために自由をとる場合が多いためです。同等の開閉。私が見つけた中で最も難しいのは、ファイル名の中央にある幅0の改行しないスペース(3日間のサーバーのダウンタイム...)でした。

9
xenoid

Bash、およびzshのような他のシェルは、現在のコマンドラインをエディターで開くことができます。 bashのデフォルトのショートカットはC-x C-eCtrlXCtrlE)、そして$VISUAL$EDITOR、emacsの最初の利用可能な場所で開きます。実際には、これは複雑なコマンドのデバッグと変更に非常に役立ちます。見方によっては、zshの方がbashよりもフレンドリーです。エディターが終了すると、bashはすぐにコマンドを実行しますが、zshはユーザーが押すのを待ちます。 Enter (コマンドを編集する機会が増えます)。

エディターでコマンドを開いた後、非ASCII文字を別の方法で表示するようにエディターを構成できます。

たとえば、次の設定を使用して with Vim

set encoding=latin1
set isprint=
set display+=uhex

enter image description here

または、他の回答の方法を適応させる:

bash-4.4$ f() { cat -A "$@"; false; }   # exit false to prevent bash from running the command
bash-4.4$ VISUAL=f
bash-4.4$ [ -f /etc/openvpn/client.conf ] && echo true  # C-x C-e here
[ -f /etc/openvpn/client.confM-BM- ] && echo true$
2
muru