こんにちは、数週間前に私はユーザーにテキストファイル名を尋ね、単語を求めるCプログラムを書いていました。その後、プログラムはテキストの左側に数字を含む入力テキストファイルを出力し、その単語がテキストファイルに表示される回数を出力します。また、対応する単語が表示される一致する行番号を出力します。
実際の例は次のとおりです。
テキストファイル名を入力してください:bond.txt
Enter the pattern to search for: Bond File contents: 1) Secret agent Bond had been warned not to tangle with Goldfinger. 2) But the super-criminal's latest obsession was too strong, too dangerous. 3) He had to be stopped. 4) Goldfinger was determined to take possession of half the supply of 5) mined gold in the world--to rob Fort Knox! 6) For this incredible venture he had enlisted the aid of the top 7) criminals in the U.S.A, including a bevy of beautiful thieves from the 8) Bronx. And it would take all of Bond's unique talents to make it fail-- 9) as fail it must. There is a match on line 1 There is a match on line 8 'Bond' appeared 2 times in the file bond.txt.
現在私はCで書いたプログラムを繰り返しますが、awkを使ってawkプログラミングを練習しようとしています。
私がこれまでに収集した内容は次のとおりです。
BEGIN{
printf("Enter filename : ")
getline file < "-"
while((getline < file)) {
{print "File Contents:"}
{printf("%5d) %s\n", NR,$0)}
}
}
ユーザーが入力した単語を検索するためにテキストファイルを1行ずつ解析するための最良かつ効率的な方法は何ですか?どのようなヒントやコツがありますか?ありがとうございます。
ベストアンサー1
$ awk '/Bond/{c++; print "There is a match on line " NR} END{print "\"Bond\" appeared " c " times in the file " FILENAME}' bond.txt
There is a match on line 1
There is a match on line 8
"Bond" appeared 2 times in the file bond.txt
どのように動作しますか?
awk はすべての入力ラインを暗黙的に繰り返します。
/Bond/{c++; print "There is a match on line " NR}
regex と一致する行の場合、
Bond
カウンタがc
増加し、一致が発生した行を示すメッセージが表示されます。 awkでこれまで読んだ行数はですNR
。END{print "\"Bond\" appeared " c " times in the file " FILENAME}
最後の行を読み取った後、一致する総数を示すメッセージが印刷されます。
複数行バージョン
コードを複数行にわたって分散したい場合:
awk '
/Bond/{
c++
print "There is a match on line " NR
}
END{
print "\"Bond\" appeared " c " times in the file " FILENAME
}
' bond.txt
ファイルサマリーの前にファイルの内容を表示
このメソッドはファイルを2回読み込みます。最初は、行番号でフォーマットされたファイルバージョンを印刷します。 2番目の印刷サマリー出力:
$ awk 'FNR==NR{printf("%5d) %s\n", NR,$0);next} /Bond/{c++; print "There is a match on line " FNR} END{print "\"Bond\" appeared " c " times in the file " FILENAME}' bond.txt{,}
1) Secret agent Bond had been warned not to tangle with Goldfinger.
2) But the super-criminal's latest obsession was too strong, too dangerous.
3) He had to be stopped.
4) Goldfinger was determined to take possession of half the supply of
5) mined gold in the world--to rob Fort Knox!
6) For this incredible venture he had enlisted the aid of the top
7) criminals in the U.S.A, including a bevy of beautiful thieves from the
8) Bronx. And it would take all of Bond's unique talents to make it fail--
9) as fail it must.
There is a match on line 1
There is a match on line 8
"Bond" appeared 2 times in the file bond.txt
上記と最初のバージョンには2つの違いがあります。まずbond.txt bond.txt
、bashを使用してコマンドラインにファイルを2回提供するか、支柱の拡張bond.txt{,}
.
次に、次のコマンドを追加しました。
FNR==NR{printf("%5d) %s\n", NR,$0);next}
FNR==NR
このコマンドは、NR がこれまでに読み込んだラインの総数で、FNR が現在のファイルから読み込んだラインの数である場合にのみ実行されます。それで、当時FNR==NR
私たちは初めてファイルを読んでいました。その後、printf
出力形式を指定し、next
スクリプトの残りのコマンドをスキップしてその行に移動します。
選ぶ
このバージョンでは、ファイルを一度だけ読み取り、フォーマットされたバージョンを印刷し、最後に印刷する要約情報を保存します。
$ awk '{printf("%5d) %s\n", NR,$0)} /Bond/{c++; s=s ORS "There is a match on line " FNR} END{print s; print "\"Bond\" appeared " c " times in the file " FILENAME}' bond.txt
1) Secret agent Bond had been warned not to tangle with Goldfinger.
2) But the super-criminal's latest obsession was too strong, too dangerous.
3) He had to be stopped.
4) Goldfinger was determined to take possession of half the supply of
5) mined gold in the world--to rob Fort Knox!
6) For this incredible venture he had enlisted the aid of the top
7) criminals in the U.S.A, including a bevy of beautiful thieves from the
8) Bronx. And it would take all of Bond's unique talents to make it fail--
9) as fail it must.
There is a match on line 1
There is a match on line 8
"Bond" appeared 2 times in the file bond.txt