文字列が "node"で始まっているかどうかをチェックしたい。 "node001"です。何かのようなもの
if [ $Host == user* ]
then
echo yes
fi
どうすれば正しくできますか?
さらに、Hostが "user1"であるか "node"で始まるかを確認するために式を組み合わせる必要があります。
if [ [[ $Host == user1 ]] -o [[ $Host == node* ]] ];
then
echo yes
fi
> > > -bash: [: too many arguments
それを正しくするには?
高度なBashスクリプトガイド のこの抜粋は、/と言います。
# The == comparison operator behaves differently within a double-brackets
# test than within single brackets.
[[ $a == z* ]] # True if $a starts with a "z" (wildcard matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).
だからあなたはそれを持っていた ほぼ 正しい。シングルブラケットではなく、 double ブラケットが必要でした。
2番目の質問に関しては、このように書くことができます。
Host=user1
if [[ $Host == user1 ]] || [[ $Host == node* ]] ;
then
echo yes1
fi
Host=node001
if [[ $Host == user1 ]] || [[ $Host == node* ]] ;
then
echo yes2
fi
どちらが反響する
yes1
yes2
Bashのif
構文は慣れがたいです(IMO)。
最近のbash(v3 +)を使っているのであれば、bash正規表現比較演算子=~
をお勧めします。
if [[ "$Host" =~ ^user.* ]]; then
echo "yes"
fi
正規表現でthis or that
と一致させるには、|
を使用します。
if [[ "$Host" =~ ^user.*|^Host1 ]]; then
echo "yes"
fi
注 - これは「適切な」正規表現構文です。
user*
は、use
と0回以上のr
の出現を意味するため、use
とuserrrr
は一致します。user.*
はuser
と0以上の任意の文字の出現を意味するので、user1
とuserX
は一致します。^user.*
は、$ Hostの先頭にあるパターンuser.*
と一致することを意味します。正規表現の構文に慣れていない場合は、 このリソース を参照してください。
注 - それぞれの新しい質問を新しい質問として尋ねると、stackoverflowがより整理され、より便利になります。参考のために、前の質問へのリンクをいつでも含めることができます。
スクリプティングの主なポイントの1つは移植性であるため、私はbashエクステンションを使用する代わりに常にPOSIX shに固執するようにしています。 ( 接続 プログラム以外に、それらを置き換えるのではありません)
Shでは、 "プレフィックス"条件を確認する簡単な方法があります。
case $Host in node*)
your code here
esac
古くて難解なshが何歳であるか(そしてbashはそれほど良い方法ではありません。より複雑で一貫性がなく、移植性が低いです)から、case
name__のような構文要素は組み込まれていますでは、結果として得られる構造は他のどの仕事と変わらない。それらは同じ方法で構成できます。
if case $Host in node*) true;; *) false;; esac; then
your code here
fi
あるいはもっと短い
if case $Host in node*) ;; *) false;; esac; then
your code here
fi
または 偶数 より短い(言語要素として!
を提示するためだけに - しかし、これは今では悪いスタイルです)
if ! case $Host in node*) false;; esac; then
your code here
fi
あなたが明示的になりたいのなら、あなた自身の言語要素を構築してください:
beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
これは実際にはかなりいいですか?
if beginswith node "$Host"; then
your code here
fi
そしてshは基本的にはジョブと文字列リスト(そして内部的にプロセスで構成され、その中からジョブが構成されている)だけなので、今でも軽い関数型プログラミングをすることさえできます。
beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
checkresult() { if [ $? = 0 ]; then echo TRUE; else echo FALSE; fi; }
all() {
test=$1; shift
for i in "$@"; do
$test "$i" || return
done
}
all "beginswith x" x xy xyz ; checkresult # prints TRUE
all "beginswith x" x xy abc ; checkresult # prints FALSE
これはエレガントです。私はshを深刻な何かのために使うことを提唱するつもりはない - それは現実世界の要件をあまりにも早く壊してしまう(ラムダがないので、文字列を使わなければならない。
確認したい文字列の部分だけを選択できます。
if [ ${Host:0:4} = user ]
フォローアップの質問には、 _または_ を使用できます。
if [[ $Host == user1 || $Host == node* ]]
私は他の方法がすでに投稿されているのを好むが、何人かの人々はそれを使いたがっている:
case "$Host" in
user1|node*)
echo "yes";;
*)
echo "no";;
esac
編集:
上記のcaseステートメントに代替案を追加しました
あなたの編集したバージョンでは、括弧が多すぎます。これは次のようになります。
if [[ $Host == user1 || $Host == node* ]];
私はここで大部分の答えがかなり正しいと思うが、それらの多くは不必要な根拠を含んでいます。 POSIXパラメータ展開 あなたが必要とするすべてをあなたに与える:
[ "${Host#user}" != "${Host}" ]
そして
[ "${Host#node}" != "${Host}" ]
${var#expr}
は、expr
と一致する最小のプレフィックスを${var}
から取り除き、それを返します。したがって、${Host}
がuser
(node
)で始まるnotである場合、${Host#user}
(${Host#node}
)は${Host}
と同じです。
expr
は fnmatch()
ワイルドカードを許可します。したがって${Host#node??}
とその仲間も動作します。
#はbashで意味があるので、私は次の解決策を得ました。
さらに、スペースなどを克服するために、文字列を ""でパックする方が好きです。
A="#sdfs"
if [[ "$A" == "#"* ]];then
echo "skip comment line"
fi
@ OP、両方のあなたの質問のためにあなたはcase/esacを使うことができます
string="node001"
case "$string" in
node*) echo "found";;
* ) echo "no node";;
esac
二番目の質問
case "$Host" in
node*) echo "ok";;
user) echo "ok";;
esac
case "$Host" in
node*|user) echo "ok";;
esac
OR Bash 4.0
case "$Host" in
user) ;&
node*) echo "ok";;
esac
Mark Rushakoffの最高ランクの回答に、もう少し構文の詳細を追加します。
表現
$Host == node*
と書くこともできます
$Host == "node"*
効果は同じです。ワイルドカードが引用テキストの外側にあることを確認してください。ワイルドカードが inside の引用符である場合、それは文字通りに解釈されます(すなわちワイルドカードとしてではありません)。
if [ [[ $Host == user1 ]] -o [[ $Host == node* ]] ];
then
echo yes
fi
[ 、 [[ および test のすべてが同じ非再帰的な文法を認識するため、動作しません。 bashのmanページの 条件式 を参照してください。
余談ですが、SUSv3は言います
KornShell由来の条件付きコマンド(二重括弧 [[]] )は、初期の提案でシェルコマンド言語の説明から削除されました。本当の問題は test コマンド( [ )の誤用であり、それをシェルに入れることは問題を解決するのに間違った方法であるという反対意見が提起されました。代わりに、適切な文書と新しいシェル予約語( ! )で十分です。
複数の test 操作が必要なテストは、エラーが発生しやすい -o フラグを使用するのではなく、 test コマンドおよびシェル論理を個別に呼び出すことによってシェルレベルで実行できます。 テスト 。
このように書く必要がありますが、 test はそれをサポートしていません。
if [ $Host == user1 -o $Host == node* ];
then
echo yes
fi
test は = を使用して文字列が等しい、より重要なことにはパターンマッチングをサポートしていません。
case
/esac
はパターンマッチングをうまくサポートしています。
case $Host in
user1|node*) echo yes ;;
esac
それはbashに依存しないという追加の利点があり、構文は移植可能です。 Single Unix Specification、シェルコマンド言語から:
case Word in
[(]pattern1) compound-list;;
[[(]pattern[ | pattern] ... ) compound-list;;] ...
[[(]pattern[ | pattern] ... ) compound-list]
esac
grep
パフォーマンスを忘れると、これはPOSIXであり、case
ソリューションよりも見栄えがよくなります。
mystr="abcd"
if printf '%s' "$mystr" | grep -Eq '^ab'; then
echo matches
fi
説明:
printf '%s'
は、printf
がバックスラッシュエスケープを展開しないようにします。 bash printf literal verbatim stringgrep -q
は、stdoutへの一致のエコーを防止します。 Bashを使用してファイルに特定の文字列が含まれているかどうかを確認する方法grep -E
は、^
に必要な拡張正規表現を有効にします呼び出し可能な関数にするために@ markrushakoffの答えを微調整しました。
function yesNo {
# prompts user with $1, returns true if response starts with y or Y or is empty string
read -e -p "
$1 [Y/n] " YN
[[ "$YN" == y* || "$YN" == Y* || "$YN" == "" ]]
}
このように使用してください。
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] y
true
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] Y
true
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] yes
true
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n]
true
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] n
false
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] ddddd
false
これは、指定されたデフォルト値を提供する、より複雑なバージョンです。
function toLowerCase {
echo "$1" | tr '[:upper:]' '[:lower:]'
}
function yesNo {
# $1: user Prompt
# $2: default value (assumed to be Y if not specified)
# Prompts user with $1, using default value of $2, returns true if response starts with y or Y or is empty string
local DEFAULT=yes
if [ "$2" ]; then local DEFAULT="$( toLowerCase "$2" )"; fi
if [[ "$DEFAULT" == y* ]]; then
local Prompt="[Y/n]"
else
local Prompt="[y/N]"
fi
read -e -p "
$1 $Prompt " YN
YN="$( toLowerCase "$YN" )"
{ [ "$YN" == "" ] && [[ "$Prompt" = *Y* ]]; } || [[ "$YN" = y* ]]
}
このように使用してください。
$ if yesNo "asfd" n; then echo "true"; else echo "false"; fi
asfd [y/N]
false
$ if yesNo "asfd" n; then echo "true"; else echo "false"; fi
asfd [y/N] y
true
$ if yesNo "asfd" y; then echo "true"; else echo "false"; fi
asfd [Y/n] n
false