私が読んでいる本 - O'ReillyのBash Shell学習では、次のようにいくつかのコードを指定します。
if [ -n "$(echo $1 | grep '^-[0-9][0-9]*$')" ]; then
howmany=$1
shift
....
....
etc
これは
grep
検索ユーティリティを使用して、適切な$1
パターンが一致するかどうかをテストします。この目的のために、^-[0-9][0-9]*$
「最初の文字にダッシュと数字、オプションで1つ以上の数字が続く」と解釈される正規表現をgrepに提供します。一致するものが見つかると、一致が返され、grep
テストは真になります。それ以外の場合は何も返されず、処理はテストに渡されgrep
ます。elif
シェルが$と*を解釈し、それを未修正の状態でgrepに渡すのを防ぐために、正規表現を一重引用符で囲みました。
それでは、正規表現が'^-[0-9]'
一重引用符のように意味を失わないのはなぜですか?通常、一重引用符の中のすべての内容は意味を失います。
ご協力ありがとうございます。
答え1
他のユーザーが既に特定の質問に回答していますが、追加します。
if [ -n "$(echo $1 | grep '^-[0-9][0-9]*$')" ]; then
これは、いくつかの理由で文字列が正規表現と一致するかどうかを確認する悪い方法です。
echo
任意のデータと一緒に使用することはできません- 上記のようにパラメータ拡張を引用符で囲んでいないのは、分割
$1
+グローブ演算子です。 grep
入力全体の正規表現を一致させるのではなく、入力の各行を一致させます。たとえば、trueを返しますfoo\n-0\nbar
。- 正規表現は長さがゼロに一致する可能性があるため、
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
を使用するには、オプション(サポートされている場合は標準オプションではないため)と組み合わせて、改行で区切られたレコードの代わりにNULで区切られたレコードを処理するように指示できますgrep
。--null
ほとんどのシェルには$1
NULを含めることができないので安全です。
if printf %s "$1" | grep --null -xq '-[0-9]+$'; then
echo match
fi
答え2
答え3
一重引用符の防止ワイルドカード(bash
ワイルドカードをこのように解釈する*
)と変数拡張を使用します$
。基本的にbash
「文字通りこの文字を取り出して渡します」と言うのですgrep
。見ればgrep
正規表現を理解できるように作られているからそれから正規表現は内部的に解釈されますgrep
。
より短いバージョン:一重引用符で囲まれた引数は、引数がコマンドに渡される前にシェル処理をエスケープする方法を提供します。
答え4
実際にその意味を失いました。grep
bashとほぼ同じ正規表現パターンを使用します。