入力に@が含まれているかどうかを確認するbashスクリプト

入力に@が含まれているかどうかを確認するbashスクリプト

こんにちは。入力に @ 記号が含まれているかどうかをチェックする bash スクリプトを書こうとしています。私は bash の初心者なので、どんな間違いでもお許しください。これまでのところ、次のとおりです。

var1="@"
var2="INPUT"

echo "input"
read INPUT

if [[ "$var2" == "$var1" ]]; then
echo "pass"
else
echo "fail"
fi

答え1

組み込みのシェル機能を使用してユーザーの入力が含まれているかどうかを確認するオプションがありますが@(他の回答で詳しく説明されています)、別の合理的な方法は外部のgrepユーティリティ:

#!/usr/bin/env bash

read -erp '> '
if grep -q @ <<<"$REPLY"; then
    echo pass
else
    echo fail
fi

-qフラグを渡すとgrep、一致する行が印刷されなくなります。(また、一致が見つかった後にそれ以上の行を読み取らないようにもなりますが、ここでは入力が 1 行しかないため、違いはありません。)

if構造を のように短縮したくなりますgrep -q @ <<<"$REPLY" && echo pass || echo failが、私は意図的にそれを避けました。

  • この場合間違った単語が印刷される唯一の方法は、pass印刷されるべきだったがecho印刷に失敗した場合にのみなので、おそらく問題ありません。その場合、echo も印刷に失敗するでしょうfail
  • 短絡&&||それ自体は適切であることが多い(そして私はよくそれらを略語として使う)が、if それなしelse)のように一緒に使用する。三元もしオペレーターあまり良い習慣とは言えません。一部のコマンドは失敗echo できる
  • ユーザーがリダイレクトスクリプトの出力を書き込み不可能なファイルやデバイスに書き込んだり、壊れたパイプライン、echo などのテキストを出力するコマンドは失敗を返す可能性があり、その場合、&&式は失敗し、式の右側が||実行されます。
  • 書き込み不可能な出力デバイスがある場合のスクリプトの動作を、 で実行することでテストできます>/dev/full

このスクリプトでは、いくつかの bash 機能を使用します。

  • -eGNU readline を有効にすると、ユーザーは矢印キーを使用してカーソルを左右に移動し、入力中に入力内容を編集できるようになります。
  • bash では、変数が指定されていない場合、readユーザーの入力が自動的に変数に格納されます。REPLY
  • ここで文字列は、<<<ユーザーの入力を に渡す便利な方法ですgrep
  • バッシュといくつかのdashなどの他のBourneスタイルのシェルは受け入れます-p。しかしPOSIX互換シェルは、-r. また、kshのように、-p別の意味を持つものもあります。
    (ゲイラ両方のことを指摘してくれた-p時々欠けているそして必ずしも「迅速」を意味するわけではありません。

bash がインストールされていない可能性のある他の OS に移植可能なスクリプトが必要な場合は、次を使用できます。

#!/bin/sh

printf '> '
read -r line

if printf '%s' "$line" | grep -q @; then
    echo pass
else
    echo fail
fi

必要に応じて、ユーザーの入力を変数に格納せずに、次のように読み取ることもできます。headの代わりにread

#!/bin/sh

printf '> '
if head -1 | grep -q @; then
    echo pass
else
    echo fail
fi

としてゲイラは言及したは、そのままの方がhead -n 1より良い構文と考えられるかもしれないhead -1正式に廃止された(ただし、現在のsed実装、または少なくとも GNU sed は-1最新バージョンでサポートされていますが、一部の非常に古いsed実装ではサポートされていません-n 1)。

としてドキュメントhead最大限の携帯性を得るために、代わりに を使用することができますsed

#!/bin/sh

printf '> '
if sed 1q | grep -q @; then
    echo pass
else
    echo fail
fi

答え2

このbashコードは入力を読み取り、入力に@シンボルが含まれている場合は「Pass」を通知します。

read -p "Input: " var
[ "${var//[^@]/}" ] && echo Pass || echo Fail

ノート:

  • [ "$var" ]bash テストです。文字列$varが空でない場合は true を返します。

  • bashの機能の1つにパターン置換があります。 のように見えます。のすべての出現をに${var//pattern/string}置き換えます。この場合、はすべての文字に一致する正規表現です。patternvarstringpattern[^@]を除外する @. したがって、少なくとも 1 つの が含まれてい${var//[^@]/}ない場合は空の文字列を返します。var@

  • 上記の 2 つを組み合わせます。

    [ "${var//[^@]/}" ]
    

    このテストは、${var//[^@]/}が空でない場合にのみ成功し、に少なくとも 1 つの が含まれている${var//[^@]/}場合にのみ空でなくなります。var@

明示的な if-then-else を使用する:

read -p "Input: " var
if [ "${var//[^@]/}" ]
then
    echo Pass
else
    echo Fail
fi

POSIX シェル

以下はdash( /bin/sh) の下で動作し、どの POSIX シェルの下でも動作するはずです。

printf "Input: "
read var
case "$var" in
    *@*) echo Pass
        ;;
    *) echo Fail
        ;;
esac

POSIXシェルは-pオプションをサポートしていませんreadprintfしたがって、代わりにとの組み合わせreadが使用されます。また、 の高度な変数拡張機能がないためbashcaseステートメントはグロブ マッチングに使用できます。

Android シェル

Android のデフォルト シェルを使用すると、次のように動作します。

echo -n "Input: "; read var
if ! [ "${var//@/}" = "$var" ]
then
    echo Pass
else
    echo Fail

答え3

bash で推奨される方法は、 のパターン マッチング機能を使用することです[[ ... ]]

#bash
read -rp "Input: " input
if [[ $input = *@* ]]; then
    printf '<%s> contains @\n' "$input"
fi

スクリプトの場合は代わりにsh使用できますcase

#sh
printf 'Input: '
read -r input
case $input in
    *@*) printf '<%s> contains @\n' "$input" ;;
esac

以下も参照テストと条件文Bash ガイドの章。

答え4

bashの新しいバージョンでは、正規表現の一致拡張テスト演算子経由=~:

$ read -p "input: " input
input: quertyuiop 
$ if [[ $input =~ \@ ]]; then echo "match"; else echo "no match"; fi
no match
$ 
$ read -p "input: " input
input: qwerty@uiop
$ if [[ $input =~ \@ ]]; then echo "match"; else echo "no match"; fi
match

POSIX 準拠のシステムであればどこでも動作する代替案としては、シェルexprで次のように使用することが考えられますdash

$ read input
qwertyuiop
$ if expr "$input" : '.*@.*' > /dev/null; then echo 'match'; else echo 'no match'; fi
no match
$ 
$ read input
qwerty@uiop
$ if expr "$input" : '.*@.*' > /dev/null; then echo 'match'; else echo 'no match'; fi
match
$ 

関連情報