grep
実行中のコマンドにその単語が引数として含まれていることを確認するために使用したいと思います。 (私はBashでそれについて知っていますが、使用したくありません)。cmd
name
!*
という変数にコマンドがあるとしましょうprocess
。
最初はecho $process | grep 'cmd name'
。これは1つのパラメータしか考慮しないため、完璧ではありません。
そのため、regexを使用して最後のパラメータとしてキャプチャできるかどうかを調べようとしましたcmd .*(?= )name
。アイデアは何でもキャプチャしてからスペースとname
(次のcmd
)をキャプチャすることです。しかし、これはうまくいきません。
これがうまくいけば、私の目標は、あらゆる立場で議論として解釈しようとすることです。
正規表現を使用してこれをどのように実行できますか?
答え1
以下の回答では、grep
コマンドラインは個々のアイテムのリストなので、テキスト行ではなくそのまま解析する必要があります。
コマンドとコマンドの引数の両方を単一の文字列(好ましくは配列)に格納するとします。変数に保存されたコマンドをどのように実行できますか?)これにより、次のことができます。
process='cmd with "some arguments" and maybe name'
set -f
set -- $process
if [ "$1" != 'cmd' ]; then
echo 'The command is not "cmd"'
exit 1
fi
shift
for arg do
if [ "$arg" = 'name' ]; then
echo 'Found "name" argument'
exit
fi
done
echo 'Did not find "name" argument in command line'
exit 1
これにより、最初にファイル名の生成が無効になります。これは、ファイル名$process
を引用符なしで別々の単語に分割し、文字列にファイル名のグローブパターン(など)が*
含まれていると、解析がめちゃくちゃになるためです。私たちはこのようなことをしていますset -f
。
次に、位置パラメータをの単語に設定します$process
。その後、そうであれば、"$1"
コマンドラインの残りの部分をcmd
見なければならないことを知っています。name
そうでない場合は、ここで停止します。
位置パラメータのリストをshift
そのままにして、パラメータを介して繰り返しを開始します。cmd
各反復では、単に引数を文字列と比較しますname
。それを見つけたら、私たちは言ってやめます。
ループが終了すると、まだパラメータが見つからなかったことがわかるので、name
これを報告して失敗で終了します。
上記の例では、パラメータはsome arguments
2つに解析されています。分離strings"some
とarguments"
、これがコマンドとその引数を単一の文字列に格納したくない理由の1つです。これはまた、name
単一のパラメータ内でパラメータを検出することを意味し"some name string"
、これは偽陽性になります。
コマンドラインが配列(たとえばbash
)に保存されている場合は、次のことができます。
process=( cmd with "some arguments" and maybe name )
if [ "${process[0]}" != 'cmd' ]; then
echo 'The command is not "cmd"'
exit 1
fi
for arg in "${process[@]:1}"; do
if [ "$arg" = 'name' ]; then
echo 'Found "name" argument'
exit
fi
done
echo 'Did not find "name" argument in command line'
exit 1
拡張は"${process[@]:1}"
完全な配列ですが、最初の項目(コマンド名)ではありません。
/bin/sh
(anddash
および他のPOSIXシェル)の場合、bash
上記はあまり冗長ではありません。
set -- cmd with "some arguments" and maybe name
if [ "$1" != 'cmd' ]; then
echo 'The command is not "cmd"'
exit 1
fi
shift
for arg do
if [ "$arg" = 'name' ]; then
echo 'Found "name" argument'
exit
fi
done
echo 'Did not find "name" argument in command line'
exit 1
これは基本的に最初のコードと同じですが、コマンドラインのすべての要素を単一のテキスト文字列に結合しないため、すべての引数(引用符など)を正しく処理します。
答え2
bashに言及したので、別のオプションはパターンマッチング演算子です=~
。
if [[ $process =~ ^cmd[[:space:]].*name([[:space:]]|$) ]]
then
_name_ was found as an argument to _cmd_
fi
cmd
これは、変数の内容がで始まり、スペースが続き、何も続いていないか、何も続かず、スペースname
または行末が続くことを確認します。