
ループでgrepとawkを使用して複数のテキストファイルをフィルタリングするスクリプトがあります。フィルタリング後に各ファイルの出力を生成すると問題が発生します。
これは私のスクリプトです。
grep_multi.sh
path=$(find /home/folder/file/source -iname "Tracert*" )
for i in "$path"
do
grep -E '^%%.*.%%$'\|'IPv4 type' $i | awk '/%%TRACERT:/ {sfx = $0; next} {print $1","$2","$3","$4","$5","$6","$7" "$8","sfx}' > filter.result.$i
done
スクリプトを実行すると、私は得ます。間違いこのように:
./grep_multi.sh: line 5: filter.result.$i: ambiguous redirect
これは変数 $path
$ find /home/folder/file/source -iname "Tracert*"
/home/folder/file/source/Tracert_1.txt
/home/folder/file/source/Tracert_2.txt
/home/folder/file/source/Tracert_3.txt
/home/folder/file/source/Tracert_4.txt
/home/folder/file/source/Tracert_5.txt
/home/folder/file/source/Tracert_6.txt
/home/folder/file/source/Tracert_7.txt
/home/folder/file/source/Tracert_8.txt
tracert_1.txt
O&M #108
%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
RETCODE = 0 Operation succeeded
The result is as follows
------------------------
Record index Response number First response time(ms) Second response time(ms) Third response time(ms) IP type Peer IP address
1 3 1 1 1 IPv4 type 10.10.10.10
2 3 1 1 1 IPv4 type 10.10.10.10
3 0 NULL NULL NULL IPv4 type Timeout
4 0 NULL NULL NULL IPv4 type Timeout
5 3 1 1 1 IPv4 type 10.10.10.10
6 3 1 1 1 IPv4 type 10.10.10.10
7 3 1 1 1 IPv4 type 10.10.10.10
答え1
変数を参照すると、"$path"
ループは一度実行され、$i
フルパスリストに展開されます。これにより、リダイレクトが次のように表示されます。
> filter.result./home/folder/file/source/Tracert_1.txt /home/folder/file/source/Tracert_2.txt ...
これは「あいまいだ」。このやや関連する質問を見ました。検索結果を繰り返すのはなぜ悪い習慣ですか?
実際にはシェルループは必要なく、必要もありませんgrep
。IPv4
次のコマンドを使用して行を選択し、現在のすべての行から名前付きファイルにリダイレクトできます。FILENAME
awk
awk '
/%%TRACERT:/ {sfx = $0; next}
/IPv4 type/ {print $1","$2","$3","$4","$5","$6","$7" "$8","sfx > "filter.result." FILENAME}
' tracert_*.txt
~のため地元のファイルを生成すると、次のような出力が生成されます。
$ head filter.result*
==> filter.result.tracert_1.txt <==
1,3,1,1,1,IPv4,type 10.10.10.10,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
2,3,1,1,1,IPv4,type 10.10.10.10,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
3,0,NULL,NULL,NULL,IPv4,type Timeout,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
4,0,NULL,NULL,NULL,IPv4,type Timeout,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
5,3,1,1,1,IPv4,type 10.10.10.10,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
6,3,1,1,1,IPv4,type 10.10.10.10,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
7,3,1,1,1,IPv4,type 10.10.10.10,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
==> filter.result.tracert_2.txt <==
1,3,1,1,1,IPv4,type 10.10.10.10,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
2,3,1,1,1,IPv4,type 10.10.10.10,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
3,0,NULL,NULL,NULL,IPv4,type Timeout,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
4,0,NULL,NULL,NULL,IPv4,type Timeout,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
5,3,1,1,1,IPv4,type 10.10.10.10,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
6,3,1,1,1,IPv4,type 10.10.10.10,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
7,3,1,1,1,IPv4,type 10.10.10.10,%%TRACERT: IPTYPE=IPv4, LOCALIP4="10.10.10.10", PEERIP4="10.10.10.10", MAXHOP=15;%%
で使用するには、find
次のことができます。
find /home/folder/file/source -iname "Tracert*" -execdir awk '
/%%TRACERT:/ {sfx = $0; outfile = "filter.result." substr(FILENAME,3); next}
/IPv4 type/ {print $1","$2","$3","$4","$5","$6","$7" "$8","sfx > outfile}
' {} +
これにより、出力ファイルが入力ファイルと同じディレクトリに配置されます。ファイルが実際に単一のディレクトリにある場合は、cd
そのディレクトリで "local" awk コマンドを使用する方が簡単です。