私が読んでいる本、O'Reilly の Learning the Bash Shell では、次のようなコードが指定されています。
if [ -n "$(echo $1 | grep '^-[0-9][0-9]*$')" ]; then
howmany=$1
shift
....
....
etc
これは、検索ユーティリティを使用して、適切なパターンに一致する
grep
かどうかをテストします。これを行うには、grep に正規表現を提供します。これは、「最初のダッシュの後に数字が続き、オプションで 1 つ以上の数字が続く」と解釈されます。一致が見つかった場合は、一致が返され、テストは true になります。一致がない場合は、何も返されず、処理はテストに渡されます。$1
^-[0-9][0-9]*$
grep
grep
elif
シェルが $ と * を解釈しないようにするために正規表現を一重引用符で囲み、変更せずに grep に渡していることに注意してください。
では、なぜ正規表現は'^-[0-9]'
一重引用符内では意味を失わないのでしょうか。通常、一重引用符内のすべては意味を失います。
助けてくれてありがとう。
答え1
他の人があなたの具体的な質問に答えていますが、私はこう付け加えておきます
if [ -n "$(echo $1 | grep '^-[0-9][0-9]*$')" ]; then
文字列が正規表現に一致するかどうかを確認する方法は、いくつかの理由から間違っています。
echo
任意のデータには使用できません- 上記のようにパラメータ展開を引用符で囲まないままにしておくのが、
$1
split+glob 演算子です。 grep
正規表現を入力全体と照合するのではなく、入力の各行と照合します。そのため、たとえば true を返しますfoo\n-0\nbar
。- 正規表現は長さが 0 であっても一致する可能性があるため、一般に が
grep
出力を生成するかどうかを確認するのは誤りです (コマンド置換によって末尾の改行文字が削除されることに注意してください)。 の終了ステータスではなく のgrep -q
終了ステータスを使用してそれに依存し、コマンド置換も回避する方が適切です。grep
[
- この
grep
コマンドは次のように簡略化できることに注意してください。grep -xE '-[0-9]+'
bash
、ksh93
およびzsh
(拡張)正規表現マッチング専用の演算子があります。これを 3 つすべて(および bash-3.1)で移植可能かつ確実に使用するには、構文は次のようになります。
re='^-[0-9]+$'
if [[ $1 =~ $re ]]; then
echo matches
fi
yash
また、zsh
以下もサポートします:
if [ "$1" '=~' '^-[0-9]+$' ]; then
echo matches
fi
文字列(基本)正規表現マッチングを実行するための標準コマンドは次のとおりですexpr
。
if expr " $1" : ' -[0-9]\{1,\}$' > /dev/null; then
echo matches
fi
^
( ではなく$
)は に暗黙的に含まれていることに注意してください。 の値が演算子である場合expr
に問題が発生するのを避けるために、先頭のスペース文字も使用します。$1
expr
また、正規表現に が含まれている場合\(...\)
、 の動作に影響することに注意してくださいexpr
。
全体として、awk
代わりに別の標準的/移植可能な方法を使用する方が適切です (awk
拡張正規表現を使用することに注意してください)。
if STRING=$1 RE='^-[0-9]+$' awk '
BEGIN{exit(ENVIRON["STRING"] !~ ENVIRON["RE"])}'; then
...
または関数を使用します:
re_match() {
STRING=$1 RE=$2 awk '
BEGIN{exit(ENVIRON["STRING"] !~ ENVIRON["RE"])}'
}
if re_match "$1" '^-[0-9]+$'
この場合、標準的なcase
構造を使用して実現することもできます。
case $1 in
("" | *[!0-9-]* | [!-]* | - | ?*-*) ;;
(*) echo match;;
esac
を使用するにはgrep
、オプション(標準オプションではないためサポートされている場合)を使用して、--null
改行で区切られたレコードではなく NUL で区切られたレコードで動作するように指示します。ほとんどのシェルでは、 に$1
NUL を含めることはできないため、これは安全なはずです。
if printf %s "$1" | grep --null -xq '-[0-9]+$'; then
echo match
fi
答え2
シングルクォートは、囲み文字をそのまま保持するようにシェルに指示します。解釈なしでgrep
引用符で囲まれた文字列は引用符なしでそのままに に渡されます。grep
が引数を探すとき、
grep
そして
^-[0-9][0-9]*$
そしてそれに基づいて行動するのです。(読むプログラムの実行方法Linux での引数の構築について興味がある場合。
bash
とgrep
は異なります。このコマンドが引用符を使用する方法により、 はbash
文字列を処理しませんが、grep
は処理します。
答え3
シングルクォートはグロビング(bash
のようなワイルドカードを解釈させ*
、 を使用することで変数を拡張します。基本的には、「それらの文字を文字通りに受け取り、 に渡す」$
と言っていることになります。 がそれらを見ると、正規表現を理解するように構築されているので、bash
grep
grep
それから正規表現は内部で解釈されますgrep
。
短縮バージョン: 引数を一重引用符で囲むと、引数がコマンドに渡される前にシェルからの処理をエスケープする手段が提供されます。
答え4
意味は失われます。bashgrep
とほぼ同じ正規表現パターンを使用します。