タイトルをできるだけ具体的に作ろうとしました。たとえば、必要です。
1
toで始まる行を含むタブ区切りのファイルがあります5
。これはブロックとして扱われます(各ブロックは複数の4
項目を持つことができます5
)。
- next は、
1
次のブロックの開始を定義する式です。 - 私のプレフィックスは常に始まる行にあります
3
。各ブロックの各行の先頭にこの単語を書きたいです。
この問題を解決する方法について考えていただきありがとうございます。必ずしもそうではありませんが、sed
そうかもしれませんが、awk
最初のsed
選択肢になります。
- 入力ファイルの例
1 foo1 2 foo1 3 bar1 | Prefix block 1 4 foo1 5 foo1 1 foo2 2 foo2 3 bar2 | Prefix block 2 4 foo2 4 foo3 5 foo2 5 foo3
- この入力例の希望出力
bar1 1 foo1 bar1 2 foo1 bar1 3 bar1 bar1 4 foo1 bar1 5 foo1 bar2 1 foo2 bar2 2 foo2 bar2 3 bar2 bar2 4 foo2 bar2 4 foo3 bar2 5 foo2 bar2 5 foo3
答え1
あなたの場合、awk
解決策は2つのステップであると思いました。つまり、入力ファイル名を指定する必要があります。二重コマンドラインのオペランドとして)。行のトークンは入力時で区切られ、\t
出力時も区別されているとします\t
。
awk 'BEGIN{FS=OFS="\t"}
NR==FNR{if ($1=="3") pre[++i]=$2;next} $1=="1" {j++} {print pre[j],$0}' input input
最初のステップでは、NR
(グローバル行カウンター)はFNR
(ファイルごとの行カウンター)と同じで、pre
最初のフィールド()が同じ行に遭遇するたびに$1
プレフィックスで配列を埋めます3
。したがって、pre
「ブロック番号」と関連するプレフィックス間のマッピングです。それ以外は何も印刷せず、すぐに次の実行行に移動します。
2番目のステップでは、j
「開始ブロック」条件が見つかるたびに(最初のフィールドが)$1
ブロック1
カウンタをインクリメントし、すべての行に対してブロックカウンタに対応するプレフィックスを追加します。
答え2
GNU sed拡張正規表現モードで実行し、-E
自動印刷をオフにして-n
印刷時期を知ることができます。
sed -En '
#--------------------------------
# printing the block in pattern space
#--------------------------------
/\n/{
s/.*\n(.*)/\1&/
P;/\n.*\n/D;$d;g
}
#--------------------------------
# collect block
#--------------------------------
:15
/^1/{
N;h
/\n5/!b15
#--------------------------------
# collect trailing 5 lines
#--------------------------------
:tail5
$bend
n
/^5/{H;$!btail5;}
#--------------------------------
# place block prefix @ eol
#--------------------------------
$!x;$g
:end
s/.*\n3\t([^\n]+)\n.*/\n&\n\1\t/
D; # take me to block print section
}
' file
結果:
bar1 1 foo1
bar1 2 foo1
bar1 3 bar1
bar1 4 foo1
bar1 5 foo1
bar2 1 foo2
bar2 2 foo2
bar2 3 bar2
bar2 4 foo2
bar2 4 foo3
bar2 5 foo2
bar2 5 foo3