ディレクトリの下の次のファイルからポート番号を取得したいと思いますVariable
。ファイルのポートラインが空の場合、iがgrep:
印刷されます。これを無視して何も印刷しない方法はありますか?
if ls $directory/*.domain.*.properties 1>/dev/null 2>&1; then
port=$(grep "domain.http.listener.port=" $directory/*.domain.*.properties |
awk -F "=" 'NR==1{print $NF}' | tr -d "\r")
fi
答え1
domain.http.listener.port=
あなたのコードは複数のファイルに含まれる式を探しているように見えます。grep
コマンドawk
はその結果の最初の行で最後に=
区切られたフィールドのみを印刷し、結果からキャリッジリターンを削除します。
不要ls
。ファイル名globbingパターンが一致するかどうかをテストするためにこれを使用しているようです$directory/*.domain.*.properties
(おそらく空白の値を分割し、$directory
そのビットに対してファイル名globbingを実行することもできます)。
ファイル名ワイルドカードパターンがファイル名と一致するかどうかをテストするには、次のようにします。
set -- "$directory"/*.domain.*.properties
directory
(単一のディレクトリの名前またはパス名のみを含める必要があると仮定したので、変数拡張を引用しました。)
if [ "$#" -gt 1 ] || [ -e "$1" ]; then ...; fi
このset
コマンドは位置パラメータ($1
、など)$2
を設定し、$3
これらのパラメータを複数(1より大きい)取得すると、パターンは$#
複数の項目と一致します。また、パターンが単一の項目と一致する場合は、を使用してその項目が存在するかどうかをテストします-e
。最後のテストでは、単一の一致と非一致(パターンが拡張されていないまま)を区別します。
awk
grep
の作業を行うことtr
ができるので、持っているパイプは実際には必要ありません。
awk -F '=' '/domain\.http\.listener\.port=/ { sub("\r","", $NF); print $NF; exit }'
それ以外の場合はすべての文字と一致するため、正規表現でドットをエスケープします。ここでは、他の場所ではなく行の末尾からキャリッジリターンを削除したいと仮定しているため、ここでのみ代わりにsub()
使用します。gsub()
すべてを一度に:
#!/bin/sh
set -- "$directory"/*.domain.*.properties
if [ "$#" -gt 1 ] || [ -f "$1" ]; then
awk -F '=' '/domain\.http\.listener\.port=/ { sub("\r","", $NF); print $NF; exit }' "$@"
fi
他のものよりも通常のファイル(またはシンボリックリンク)で実行する方が合理的であるため、-e
テストをテストに変更しました(ただし、一致する項目が複数ある場合は、どのファイルのファイル形式もテストしません)。-f
awk
"$@"
パターンは、コマンドで一致するように管理するすべての名前(個別に引用)に拡張されます。set
最初の一致を含むファイルのパス名が必要な場合は、それを変更して特殊変数(たとえば)awk
の内容を印刷することもできます。欲しいFILENAME
print FILENAME, $NF
みんな(最初のファイルの最初の一致だけでなく)一致した後exit
。
ファイル名ワイルドカードパターン(あなたのような)と一致するファイルが何百または何千ものある場合、この回避策は失敗します。この場合、シェルループを実行できます。
for pathname in "$directory"/*.domain.*.properties; do
if [ -f "$pathname" ]; then
awk -F '=' '
/domain\.http\.listener\.port=/ {
sub("\r","", $NF); print $NF; found=1; exit
}
END { exit !found }' "$pathname" && break
fi
done
ここでは、目的のテキストの印刷中に終了状態が0の状態で終了することを選択しましたがawk
、これによりループが終了します。