フィールド1を別の行に分割し、作成された各新しい行に対してコピーされたフィールド2を保持する方法

フィールド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この道は行く道ですか?

答え1

最初のフィールドは行のフィールド数を保持し、where変数を使用してフィールドにアクセスでき、$1ループはCとほぼ同じように機能します。だから:NF$ii

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

(フィールド区切り文字でスペースとタブを区別しません。)

答え2

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"

答え3

もう一つの奇妙な:

~$>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; }

答え4

awkで分割機能を使用することもできます。

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

関連情報