Bashコマンドラインのread、echo、およびgrepコマンドについて

Bashコマンドラインのread、echo、およびgrepコマンドについて

Bashラインで何が起こっているのかを段階的に説明できる人はいますか?私はここに初めて来ましたが、特にこのコードが次にどのように機能するかを理解しようとしていますecho

read char; echo -e "YES\nNO\n" | grep -i $char

答え1

charこの行のコマンドは、ユーザーが対話的に文字列を変数として読み込みます。

echo+パイプはgrep入力文字列が正の文字列であることを確認しようとします。大文字と小文字を区別せずに、入力文字列(入力文字列をパターンとして使用)YESと単語の合計を比較してこれを行います。NOユーザーが単語の大文字、小文字、または部分文字列を入力すると結果はにYESなりYES、文字列の大文字、小文字、または部分文字列を入力すると結果はにNOなりますNO。このような内容を入力すると空のmaybe出力が発生します。

このアプローチの欠点は、たとえば、ユーザーが と と入力すると、両方が一致することです。.なぜなら、YESドットNOgrepすべての文字に一致する正規表現として扱われるからです。$char呼び出しに引用符がないため、ユーザーがgrep入力/*/*/*/*/../../../../*/*/*/*などのシェルグローブパターンを入力した場合(たとえば、次から取得)bash / POSIXシェルで変数を引用することを忘れてしまうセキュリティリスク)。-r -o -e . /たとえば、コマンドの出力を歪ませることもできます。例えば、(これは、各非バイナリファイルの各文字に対して、そのファイルが属するファイルのパス名の前に別々の行を出力します)。

あなたが示すコードは、本質的にユーザー入力を使用するという点で「奇妙で珍しい」です。パスワードつまり、ユーザー入力を次のように使用します。模様、静的テストデータこの可変パターンの場合。これは、ユーザーの入力を受け取り、静的スキーマに対してこの変更可能なデータをテストする通常行われる操作とは反対です。

次のようなコードを使用する方が一般的です。

read -p 'Yes/[N]o: ' yesno
if [[ $yesno == [Yy]* ]]; then
   # code for affirmative
else
   # code for non-affirmative
fi

上記のコードは、ユーザーから文字列を読み取り、文字列が文字またはy文字Yで始まるかどうかをテストします。そうであれば、ステートメントの最初の分岐が選択されif、それ以外の場合はデフォルトで選択されますelse

明らかに、単語全体をテストしたり、YES大文字[Yy][Ee][Ss]と小文字を区別せずに一致をテストしたり、検証を介して入力ループを変更したりできます。

while true; do
    read -p 'Yes/No: ' yesno

    if [ "$yesno" = Yes ] || [ "$yesno" = No ]; then
        break
    fi

    echo 'Please enter "Yes" or "No"' >&2
done

# $yesno is either Yes or No here

(または同様のもの)。

上記の2つのサンプルコードが、ユーザー入力をパターンではなくデータとしてのみ使用する方法に注意してください。

元のコマンドを少なくとも寛容なものに書き換えると(ただし、機能が異なり、完璧ではないかもしれません)

read yesno; printf '%s\n' "${yesno^^}" | grep -i -w -E 'yes|no'

ユーザーがまたはを入力すると、大文字またはがYES返されます。これは、ユーザーが単純な等以上のコンテンツを入力する必要があるという点で機能的に異なります。NOyesnoeyes

答え2

いいですね。各コマンドを順番に実行しましょう。

read char

これは標準入力(通常はキーボードですが、間接ファイルまたはパイプストリームの場合があります、以下を参照)から読み取られ、受信したデータを名前付き変数に配置しますchar

echo -e "YES\nNO\n"

echo提供された引数は標準出力(通常は端末)として印刷されます。この-eスイッチ(通常は必ずしもそうではなく、echo一貫した実装にはいくつかの問題があります)を使用すると、e一部の基本フォーマットに対して特定の文字をエスケープできます。この場合、\nエスケープされたを使用しており、newlineの略ですn

grep -i $char

grep提供されたパターンに一致する項目があるかどうかを確認するために提供された入力を検索するツールです。このスイッチは大文字と小文字を区別せずに検索-iするように指示します。i

それとコマンド|の間に「パイプ」があります。これは、第1のコマンドの出力を第2のコマンドの入力に接続する。つまり、数字は変数の内容に反映されたパターンを検索します。echogrepgrepchar

YES
NO

このコマンドシーケンスの実際の結果は、提供された入力(変数名に基づいて単一文字と見なされますが解決されません)を見ることです。文字がY、、、、またはの場合、E出力はです。文字が、、、またはの場合、出力はです。ただし、(たとえば)入力がまたはの場合は何も出力されません。SyesYESNOnoNOyone

前述のように、入力が文字であるという仮定は確認されません。これは、与えられたコマンドシーケンスの例では唯一のアンチパターンではありません。たとえば、変数は参照されず、正規表現ツール(grep)は入力の正規表現ワイルドカードフィルタリングなしで使用されています。

答え3

で「文字」(文字列ではない)を読みます/dev/stdin。意味:自分で入力してください。

/dev/stdoutその後、コンソールを意味する2行が出力されます。

次に、パイプ("|")を介して大文字と小文字を区別しない入力バージョンに移動します。

つまり、「bar」と入力すると何も出力せずに完了しますが、「y」と入力すると「YES」行が出力され、「Y」も強調表示される可能性が高くなります。

関連情報