例:
入力ファイル
A<0>
A<1>
A_D2<2>
A_D2<3>
A<4>
A_D2<6>
A<9>
A_D2<10>
A<13>
望ましい出力:
A<0>
A<1>
A_D2<2>
A_D2<3>
A<4>
-----
A_D2<6>
-----
-----
A<9>
A_D2<10>
-----
-----
A<13>
山かっこ内の数値に注意してください。
数が連続的でない場合は、数が有効であるまで、いくつかの記号を追加します(または改行を追加します)。
この場合、番号5、7、8、11、12はありません。
誰かがawkまたはsed(grepでも)コマンドを使用してこの問題を解決できますか?
私はLinuxの初心者です。コマンドライン全体の詳細を説明してください。
これを行うためにgrep
またはsed
を使用することはお勧めしません。grep
はカウントできず、sed
は本当にだからですあらゆる種類の計算を行うのは困難です(正規表現ベースのカウントである必要があります 専用 を除くほとんどの人にとってスターターではありません)。
$ awk -F '[<>]' '{ while ($2 >= ++nr) print "---"; print }' file
A<0>
A<1>
A_D2<2>
A_D2<3>
A<4>
---
A_D2<6>
---
---
A<9>
A_D2<10>
---
---
A<13>
awk
コードは、0
が最初の数値であると想定し、現在の行のwanted行番号を維持します変数nr
内。 1つまたは複数の行を挿入する必要がある数値が入力から読み取られる場合、これはwhile
ループ(nr
変数もインクリメントする)によって行われます。
<...>
内の数値は、<
および>
をフィールド区切り文字として使用するように指定することによって解析されます。番号は$2
(2番目のフィールド)になります。
これはおそらく効率的ではありません...
$ tr '<' '\t' < testfile | tr '>' ' ' \
| awk '{ while (NR + shift <= $2) { print "-----"; shift++ }; print }' \
| tr '\t' '<' \
| tr ' ' '>'
A<0>
A<1>
A_D2<2>
A_D2<3>
A<4>
-----
A_D2<6>
-----
-----
A<9>
A_D2<10>
-----
-----
A<13>
最初に、tr
を使用して、ファイルから2つのタブ区切りフィールドを取得します。
次に、もう一度tr
を使用して「>」をスペースに置き換えます。そうしないと、awkコマンドが失敗するためです:-/
このあたりのawkの専門家はおそらく笑うでしょう:-)
3番目に、awk
-コマンドは、処理された行数を2番目のフィールドと比較します。行数が少ない場合は、マーカーが印刷され、前の比較の行数に追加されるshift
が増加します。
4番目と5番目:以前にtr
で行った変更を元に戻します。
https://unix.stackexchange.com/a/190707/364705 からインスピレーションを得ました
私はawk
の人ではありませんが、これもそうしているようです。私は常に改善の余地があります。
awk -F '[<>]' -v num=0 '
{
while(num < $2) {
print "----";
num++
}
print $1"<"$2">"
num++
}' file
最初に、フィールド区切り文字を<
および>
の文字と一致するように設定し、各行がこれらの文字で分割されるようにします。たとえば、最初の行は$1=A
と$2=0
に割り当てられます。
次に、変数num=0
を設定します。これを行カウンターとして使用します。現在の行の番号$2
が行カウンターより大きい場合は、----
を出力し、両方の値が等しくなるまでカウンターを繰り返します。次に、$1<$2>
を出力し、カウンターをインクリメントします。
最初の行の数字がゼロでない場合でも、最初の行の前に破線を印刷しないようにするには、次のようにします。
$ cat tst.awk
BEGIN { FS="[<>]+" }
{
curr = $(NF-1)
if ( NR > 1 ) {
for (i=prev+1; i<curr; i++) {
print "-----"
}
}
print
prev = curr
}
$ awk -f tst.awk file
A<0>
A<1>
A_D2<2>
A_D2<3>
A<4>
-----
A_D2<6>
-----
-----
A<9>
A_D2<10>
-----
-----
A<13>
先読みと後読みを使用し、ダッシュのみを追加する正規表現を使用して、この問題に対処できます。
$ Perl -0777 -pe 's/^.*<(\d+)>.*\n\K(?=.*<(\d+)>.*$)/qq[-----\n] x ($2-$1-1)/gem' file
結果:
A<0>
A<1>
A_D2<2>
A_D2<3>
A<4>
-----
A_D2<6>
-----
-----
A<9>
A_D2<10>
-----
-----
A<13>