前任:
输入文件
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 初学者。请解释整个命令行的详细信息。
答案1
不建议使用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
应该是第一个数字,然后维护通缉变量中当前行的行号nr
。如果从输入中读取一个数字,需要插入一行或多行,则这是通过循环完成的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
从文件中获取两个制表符分隔的字段。
其次,我tr
再次使用空格替换 '>',因为否则我的 awk 命令将失败:-/
这里的 awk 专业人士现在可能会笑:-)
第三,awk
-命令将处理的行数与第二个字段进行比较。如果行数较小,它将打印标记并增加该标记,shift
并将其添加到先前比较的行数中。
第四和第五:我正在撤消之前使用tr
.
我从中得到了一些灵感https://unix.stackexchange.com/a/190707/364705
答案3
我不是awk
男人,但这似乎也能做到这一点。我始终乐于接受改进:
awk -F '[<>]' -v num=0 '
{
while(num < $2) {
print "----";
num++
}
print $1"<"$2">"
num++
}' file
首先,我们设置字段分隔符以匹配字符<
和>
,因此每行都在这些字符处分割。例如,第一行将分配给$1=A
和$2=0
。
然后我们设置变量num=0
。我们将其用作行计数器:如果当前行数$2
大于行计数器,则 print ----
,增加计数器重复,直到两个值相等。然后打印$1<$2>
并递增计数器。
答案4
我们可以通过正则表达式使用lookahead和lookbehind来解决这个问题,并且只添加破折号:
$ 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>