web-dev-qa-db-ja.com

フィールド1を個別の行に分割し、作成された新しい行ごとにフィールド2をコピーしたままにする方法

入力:

注:タブで区切られた2つの列、列2の単語を区切る通常のスペース。

1   the mouse is dead
2   hit the wall
3   winter lasts forever

必要な出力:

1   the
1   mouse
1   is
1   dead
2   hit
2   the
2   wall
3   winter
3   lasts
3   forever

awkはこれを実現する方法ですか?

7

最初のフィールドは$1で、NFは行のフィールド数を保持し、$iでフィールドにアクセスできます。ここで、iは変数であり、ループはCとほぼ同じように機能します。

$ awk '{for (i = 2; i <= NF; i++) printf "%s\t%s\n", $1, $i} ' < blah
1       the
1       mouse
...

(これは、フィールド区切り文字としてのスペースとタブを区別しません。)

12
ilkkachu

GNU sed

sed -E 's/^((\S+\s+)\S+)\s+/&\n\2/;P;D'

POSIX sed構文では見苦しいです:

s='[[:space:]]\{1,\}' S='[^[:space:]]\{1,\}'
sed "s/^\(\($S$s\)$S\)$s/&\\
\2/;P;D"
5

別のawkのもの:

~$>echo '1   the mouse is dead
2   hit the wall
3   winter lasts forever
' | awk 'BEGIN { RS="[[:space:]]+"; } /^[[:digit:]]+$/ {line=$1; next}; { print line "\t" $1; }'
1   the
1   mouse
1   is
1   dead
2   hit
2   the
2   wall
3   winter
3   lasts
3   forever

少し良くレイアウトされています。

# split all parts into single Word records.
BEGIN { RS="[[:space:]]+"; } 

# if the record is a number the save
/^[[:digit:]]+$/ { line=$1; next }; 
# else use last saved line number and this record to format output.
{ print line "\t" $1; }
2
Guy

Awkでsplit関数を使用することもできます。

awk -F"\t" 'BEGIN { OFS="\t" } { cols=split($2,arr," "); for ( i=1; i<=cols; i++ ) { print $1,arr[i] }}'
2
Stefan