Bashの値に基づいて2つのファイルの行を連結します。

Bashの値に基づいて2つのファイルの行を連結します。

Bashスクリプトを使用して2つのファイルを結合しようとしています。

ファイル1:

John (20)
Jim (30)
Adrian Lors (23)

ファイル2:

Jim
some jim info here
some jim other info
more jim info

John
some john info here
some john other info
more john info

Adrian Lors
some adrian info here
some adrian other info
more adrian info

予想される結果は次のようになりますが、試すことはできません。

ファイル3:

Jim (30)
some jim info here
some jim other info
more jim info

Adrian Lors (23)
some adrian info here
some adrian other info
more adrian info

John (20) 

some john info here
some john other info
more john info

理想的には、file3を括弧内の数字でソートしたいのですが、最大の問題は、2つのファイルを結合できないことです。シェルスクリプトでこれをどのように達成できますか?

ありがとう

答え1

これがあなたが探しているものかもしれません:

$ cat tst.awk
NR==FNR {
    val = $NF
    gsub(/^[[:space:]]+|[[:space:]]+[^[:space:]]+[[:space:]]*$/,"")
    map[$0] = val;
    next
}
FNR==1 {
    FS = OFS = "\n"
    ORS = "\n\n"
    $0 = $0
}
{
    $1 = $1 " " map[$1]
    print
}

$ awk -f tst.awk file1 RS= file2
Jim (30)
some jim info here
some jim other info
more jim info

John (20)
some john info here
some john other info
more john info

Adrian Lors (23)
some adrian info here
some adrian other info
more adrian info

答え2

join、GNU、sedおよび以下を使用してくださいsort

join -t '#'\
  <(sed 's/ (/#(/' file1 | sort)\
  <(sed -z 's/\n/#/g; s/##/\n/g; $ s/#$//' file2 | sort)\
  | sort -t'#' -nrk2.2\
  | sed '2,$ s/^/\n/g; s/#/ /; s/#/\n/g'

このコマンドでは、未使用の文字が一時フィールドの区切り文字#と改行として使用されます。

出力:

Jim (30)
some jim info here
some jim other info
more jim info

Adrian Lors (23)
some adrian info here
some adrian other info
more adrian info

John (20)
some john info here
some john other info
more john info

詳細

最初のパラメータjoin

$ sed 's/ (/#(/' file1 | sort
Adrian Lors#(23)
Jim#(30)
John#(20)

各行の最後の空白文字を結合区切り文字に置き換え、#結果をソートします。


2番目のパラメータjoin

$ sed -z 's/\n/#/g; s/##/\n/g; $ s/#$//' file2 | sort
Adrian Lors#some adrian info here#some adrian other info#more adrian info
Jim#some jim info here#some jim other info#more jim info
John#some john info here#some john other info#more john info
  • sed -z改行を簡単に置き換えるためにファイルを読み取るために使用されます。
  • 最初の2つの代替文字は、各名前のテキストを1行に配置するために使用されます。各改行文字を one に置き換え###後ろの 2 つを 1 つの改行文字に置き換えます。
  • 最後の代替文字#はファイルの末尾から削除されます(最後の改行文字)。
  • 結果を並べ替えます。

接続して並べ替えた結果は次のとおりです。

$ join -t '#'\
    <(sed 's/ (/#(/' file1 | sort)\
    <(sed -z 's/\n/#/g; s/##/\n/g; $ s/#$//' file2 | sort)\
    | sort -t'#' -nrk2.2
Jim#(30)#some jim info here#some jim other info#more jim info
Adrian Lors#(23)#some adrian info here#some adrian other info#more adrian info
John#(20)#some john info here#some john other info#more john info

最初のフィールドで 2 つの手続き型置換を連結し、2 番目のフィールドを位置 2 から始めて、逆の順序で数字でソートします。


残りの部分

... | sed '2,$ s/^/\n/g; s/#/ /; s/#/\n/g'

結合区切り文字を置き換えて改行文字を再インポートします。

  • 行2(空白行)で始まる各行の先頭に改行文字を追加します。
  • 各行の最初の行を#空白文字に置き換え、残りの#'を改行文字に置き換えます。

答え3

働く:

理想的には、file3を括弧内の数字でソートしたいと思います。

努力する

$ sort -t\( -k2 file1 | awk '
FNR == NR       {X = $1;
                 sub ($1 FS, "")
                 T[X] = $0
                 next
                }
                {X = $0
                 sub (/ [^ ]*$/, "", X)
                }
X in T          {print $0, T[X] 
                }
' RS= FS="\n" file2 RS="\n" ORS="\n\n" OFS="\n" -
John (20)
some john info here
some john other info
more john info

Adrian Lors (23)
some adrian info here
some adrian other info
more adrian info

Jim (30)
some jim info here
some jim other info
more jim info

sort必要に応じて、「括弧内の数字」でfile1をソートし、file2を読み取り、レコード区切り文字で空白行を使用して$ 1で索引付けされた配列に保存し、file1のソートされた結果を使用して索引ごとに配列を印刷します。

関連情報