シェルの区切り文字に基づいてデータをフィルタリングする

シェルの区切り文字に基づいてデータをフィルタリングする

次のようなデータを含むファイルがあります:

"google1|yoo|dummy|yes|wow|/" + VARIABLE + "/"
"google2|hub|lab|dummy|yes|/" + VARIABLE + "/"
"google3|short|lab|yoo|/" + VARIABLE + "/"
"google4|hello|good-guy|bad-girl|lol|dummy|/" + VARIABLE + "/"
"google5|good-guy|a4-123|yoo|/" + VARIABLE + "/"
"google6|bad-girl|b4-124|hub|/" + VARIABLE + "/"

ここで、区切り文字「|」(パイプ)間の文字列のリストを取得したいと思います。

出力は次のようになります

yoo
dummy
yes
wow
hub
hello
good-guy
bad-girl
a4-123
b4-124
dummy
lol
short
lab

基本的に、区切り文字フィルタ後の文字列のリストから一意の値を取得したいのです。awkを使用してみました。

awk -F"|" '{gsub(/\).*/,"",$2);print $2}' file

しかし、間違ったデータを取得しました。

答え1

grepオプションがある場合pcre:

$ grep -oP '\|\K[^|]+(?=\|)' ip.txt | sort -u
a4-123
b4-124
bad-girl
dummy
good-guy
hello
hub
lab
lol
short
wow
yes
yoo
  • -o一致するパターンのみを印刷する
  • -Ppcre正規表現を使用する
  • \|\K|抽出する文字列の前にある かどうかを確認するための肯定的な後読み
    • 同様に、抽出する文字列の後に(?=\|)何かがあるかどうかを確認するために、肯定的な先読みを行う。|
  • [^|]+抽出する文字列 - 単純に否定して|、そのような文字の1つ以上を取得します
  • sort -uユニークな価値を得る

これらの文字列が見つかった順序を保持する場合:

$ grep -oP '\|\K[^|]+(?=\|)' ip.txt | awk '!seen[$0]++'
yoo
dummy
yes
wow
hub
lab
short
hello
good-guy
bad-girl
lol
a4-123
b4-124

答え2

順序を気にしない場合は、Perlハッシュを使用して一意性を確保することができます。例:

$ perl -lne '$h{$_}++ for /(?<=\|).*?(?=\|)/g; END{print for keys %h}' file
short
b4-124
lol
yes
bad-girl
lab
yoo
good-guy
hub
dummy
hello
a4-123
wow

見るPerl で正規表現に一致するハッシュを作成する

答え3

以下はどうでしょうか?

cut file -d'|' -f2,3,4 | tr '|' '\n'

上記のコマンドは固定数の列 (3) を出力します。 の最初の出現までの可変数の列を出力したい場合は/、次のようにします。

cut -d'/' -f1 file | cut  -d'|' -f2- | tr '|' '\n'

答え4

出力には「ダミー」の繰り返しがあります。これは、以下のスクリプトで得られる結果です。

   awk -f f1.awk /tmp/f1
    short
    hub
    wow
    hello
    a4-123
    b4-124
    yes
    yoo
    lol
    bad-girl
    good-guy
    lab
    dummy

    cat f1.awk 
    {
      n=split($1,a,"|")

      for(i=2; i<n; i++) {
        arr[a[i]] = a[i] 
      } 
    }   
    END{
      for (var in arr) 
        print(var)  
    }

関連情報