以下はテキストです。
* Tue This is the first line
– info 1
– info 2
– info 3
* Wed This is not to be included
このテキストの出力は次のようになります。
* Tue This is the first line
– info 1
– info 2
– info 3
注:awkとsedを試しましたが、出力を取得できませんでした。問題は、STARTとENDが同じ「*」(アスタリスク)で、最初の項目を出力に含める必要があることです。
答え1
私はこれを正しく理解することを願っています。このスクリプトは、2 行目からバッファーの終わりまで*
すべてを削除し、例で目的の出力を生成します。
sed -n 'H;1h;$x;$s/\(\*[^*]*\)\n\*.*$/\1/p'
説明H
保持バッファにすべての行()を追加します。最後の行では、ホールドバッファとパターンバッファ($x
)を置き換えてファイル全体を1つのパターンにします。このモードでは、保持される部分が設定\(\)
および維持され( \1
)、改行内のすべての内容は*
削除されます。
これは説明には適していますが、すべての可能な例に合わない場合は、スクリプトを変更できます。
答え2
perl -lne 'if ( m?^\*? ... m?^\*? ) { print if !// || !$a++ }'
sed -e '
/^\*/!d
:loop
$q; N
/\n\*/!bloop
s/\(.*\)\n.*/\1/;q
'
sed -e '
/^\*/!d
:loop
n
//!bloop
Q
'
答え3
サンプルテキストを変数に保存します。
$ SAMPLE=$(cat <<EOF
* Tue This is the first line
– info 1
– info 2
– info 3
* Wed This is not to be included
* Tue This is the first line
– info 1
– info 2
– info 3
* Wed This is not to be included
EOF
)
処理awk
方法$SAMPLE
:
$ awk '{if($1~"\*"){if(p==1){p=0;next}else{p=1}}if(p==1){print $0}}' <<<"$SAMPLE"
* Tue This is the first line
– info 1
– info 2
– info 3
* Tue This is the first line
– info 1
– info 2
– info 3
編集する
コメントで提案したように、驚くほどエレガントなawk
ソリューションがあります。
$ awk '/^\*/{p=!p};p' <<<"$SAMPLE"
* Tue This is the first line
– info 1
– info 2
– info 3
* Tue This is the first line
– info 1
– info 2
– info 3
仕組み:
/^\*/{p=!p};
p
- の値が変わります1
。正規表現を初めて発見すると0
なります。二番目に見つかるとそうなります。1
/^\*/
p
0
p
- これはと同じですp{print}
。は基本操作なので、print
前提条件がその値に評価されると(この場合になると)awk
常に印刷されます。true
p
1