awk、sed、grepを使用したグループ入力

awk、sed、grepを使用したグループ入力

次の入力ファイルがあります。

1001   Ivanov I.I: chess 
2021   Petrov P.P: chess, football
3352   Sidorov S.S:  
1000   Putin V.V: judo
8773   Schwarzenegger A: judo, chess, football

出力は次のようになると予想されます。

-- chess -- 
  Ivanov I.I
  Petrov P.P
  Schwarzenegger A
-- football --
  Petrov P.P
  Schwarzenegger A
-- judo --
  Putin V.V.
  Schwarzenegger A

答え1

これは、質問で指定されたとおりに正確に作業を実行する醜い「oneliner」です。

for tag in `cat input |cut -d: -f2 |sed 's/<\/p>//g' |sed '/^[[:space:]]*$/d' |tr "," "\\n" | sed 's/[[:space:]]//g' | sort -u`; do echo "<p>-- $tag --</p>"; grep $tag input | awk '{print $2, $3}' | sed 's/://g' | sed 's/^/ <p>/' | sed 's/$/<\/p>/'; done;

しかし、私はこの正確な問題を解決するのを助けるためにこの記事を書くのではありません。私は意図的に非常に具体的な作業を行う部分としてソリューションを作成しました。だから欲しいなら勉強するこの特定の問題を解決するよりも、これらのツールの使用方法を読んでください!

ビットごとにどのように機能するかを見てみましょう。

for tag in-という名前の新しい変数を定義しますtag。これは必要なタグに使用されます。

cat input- 名前付きファイルを読み取り、inputこの名前をファイル名に変更します。

|パイプは一連のコマンドを介してデータを取得する楽しい方法です。

cut -d: -f2- コロンを:区切り文字として使用して、2番目のフィールドを取得します。これにより、各行のコロンの後にテキストが表示されます。

sed 's/<\/p>//g'- 入力の各行から閉じている段落記号を削除します。

この時点で、データは次のようになります。

 chess 
 chess, football

 judo
 judo, chess, football

次に、空白のみで構成された空行を削除してみましょう。一部の行にはリンクタグがないためです。

sed '/^[[:space:]]*$/d'- 空白のみのすべての行を削除します。すごい!

tr "," "\\n"- 各ラベルが別々の行に表示されるように、すべてのカンマを改行文字に置き換えます。

sed 's/[[:space:]]//g'- 行の先頭の余分なスペースを削除します。

sort -u- タグをアルファベット順に並べ替え、重複したタグを削除します。今、私たちは重複せずにすべてのタグの完全なリストを順番に持っています。

chess
football
judo

今、それぞれこれらのタグに対して、次の手順を実行します。

echo "<p>-- $tag --</p>"- 指定されたとおり、段落htmlタグ、2つのダッシュ、タグ名、2つのダッシュ、および閉じる段落タグを印刷します。

grep $tag input- 特定のタグを持つ行を探す

awk '{print $2, $3}'- 精子体名フィールド(姓+イニシャル)

sed 's/://g'- awkが略語の一部と見なすコロンを削除します。

sed 's/^/ <p>/'- 各行の先頭に段落タグを追加します。

sed 's/$/<\/p>/'- 各行の末尾に閉じる段落タグを追加します。

done;- 終わりました、はい!

結果は次のとおりです。

$ for tag in `cat input |cut -d: -f2 |sed 's/<\/p>//g' |sed '/^[[:space:]]*$/d' |tr "," "\\n" | sed 's/[[:space:]]//g' | sort -u`; do echo "<p>-- $tag --</p>"; grep $tag input | awk '{print $2, $3}' | sed 's/://g' | sed 's/^/  <p>/' | sed 's/$/<\/p>/'; done;
<p>-- chess --</p>
  <p>Ivanov I.I</p>
  <p>Petrov P.P</p>
  <p>Schwarzenegger A</p>
<p>-- football --</p>
  <p>Petrov P.P</p>
  <p>Schwarzenegger A</p>
<p>-- judo --</p>
  <p>Putin V.V</p>
  <p>Schwarzenegger A</p>

編集:誰かがラベルが入力の一部ではないと言いました。これにより、状況が少し単純化されます。

$ for tag in `cat input |cut -d: -f2 |sed '/^[[:space:]]*$/d' |tr "," "\\n" | sed 's/[[:space:]]//g' | sort -u`; do echo "--$tag --"; grep $tag input | awk '{print $2, $3}' | sed 's/://g'; done; 
--chess --                                                        
Ivanov I.I
Petrov P.P
Schwarzenegger A
--football --
Petrov P.P
Schwarzenegger A
--judo --
Putin V.V
Schwarzenegger A

答え2

awk -F: '{
    sub( "[ 0-9]+", "", $1 )
    gsub( " +", "", $2 )
    cz=split( $2,comp,"," )
    for( c=1; c<=cz; c++ ) {
        if( comp[c] ) {
            if( ! allcomp[comp[c]] ) 
                fifocomp[++fifoc] = comp[c]
            allcomp[comp[c]] = allcomp[comp[c]] "  " $1 "\n" 
        }
    }
} END {
    for( c=1; c<=fifoc; c++ ) {
        print "-- " fifocomp[c] " --"
        printf "%s", allcomp[fifocomp[c]]
    }
}' file

出力:

-- chess --
  Ivanov I.I
  Petrov P.P
  Schwarzenegger A
-- football --
  Petrov P.P
  Schwarzenegger A
-- judo --
  Putin V.V
  Schwarzenegger A

関連情報