一度に1行ずつファイルを繰り返し、一貫した出力を生成するbashスクリプトを作成したいと思います。
はい.txt
ALBERT some a BRYAN some b CLAUDIA some c DAVID some d ERIK some e
ALBERT some a BRYAN some b ERIK some e
ALBERT some a BRYAN some b DAVID some d
いくつかの注意:
- タグごとに単語数が異なります。
- キーワードは常に同じ順序で表示されます。
- キーワードの完全なリストが提供され、開始する前に指定できます。
希望の出力:
some a; some b; some c; some d; some e
some a; some b;;; some e
some a; some b;; some d;
sedを使用すると、キーワードをセミコロンに1つずつ簡単に置き換えることができます。
sed -i 's/ALBERT/;/g' "example.txt"
特定のキーワードがない場合は、awkを使用して各行を繰り返して必要なセミコロンを追加するにはどうすればよいですか?どのようなカウンターを導入する必要があると思いますか?
ベストアンサー1
一部のタグ(「ALBERT」のような名前)が他の行に欠けているかのように最初の行に欠落している可能性があると仮定すると、2段階のアプローチを使用して最初にすべてのタグを識別してから、すべてのタグを印刷する必要があります。その行に表示されるかどうかに関係なく、すべての行に適用される値。
$ cat tst.awk
BEGIN { OFS=";" }
NR==FNR {
for (i=1; i<NF; i+=3 ) {
if ( !seen[$i]++ ) {
tags[++numTags] = $i
}
}
next
}
{
delete tag2val
for (i=1; i<NF; i+=3) {
tag = $i
val = $(i+1) FS $(i+2)
tag2val[tag] = val
}
for (tagNr=1; tagNr<=numTags; tagNr++) {
tag = tags[tagNr]
val = tag2val[tag]
printf "%s%s", val, (tagNr<numTags ? OFS : ORS)
}
}
$ awk -f tst.awk example.txt example.txt | column -t -s';' -o'; '
some a; some b; some c; some d; some e
some a; some b; ; ; some e
some a; some b; ; some d;
上記のコードは、すべての入力に表示される順序で各行のすべてのラベル値を出力します。
ラベルを列ヘッダーとして処理するには:
$ cat tst.awk
BEGIN { OFS=";" }
NR==FNR {
for (i=1; i<NF; i+=3 ) {
if ( !seen[$i]++ ) {
tags[++numTags] = $i
}
}
next
}
FNR==1 {
for (tagNr=1; tagNr<=numTags; tagNr++) {
tag = tags[tagNr]
printf "%s%s", tag, (tagNr<numTags ? OFS : ORS)
}
}
{
delete tag2val
for (i=1; i<NF; i+=3) {
tag = $i
val = $(i+1) FS $(i+2)
tag2val[tag] = val
}
for (tagNr=1; tagNr<=numTags; tagNr++) {
tag = tags[tagNr]
val = tag2val[tag]
printf "%s%s", val, (tagNr<numTags ? OFS : ORS)
}
}
$ awk -f tst.awk example.txt example.txt | column -t -s';' -o'; '
ALBERT; BRYAN ; CLAUDIA; DAVID ; ERIK
some a; some b; some c ; some d; some e
some a; some b; ; ; some e
some a; some b; ; some d;