输入.txt:
8B0C
remove
8B0D
remove
8B0E
remove
8B0F
8B10
remove
8B14
remove
8B15
remove
8B16
remove
8B17
remove
8AC0
8AC1
remove
8AC2
remove
8AC3
remove
8AE4
8AE5
8AE6
remove
期望的输出:
8B0F
8AC0
8AE4
8AE5
如果该行或下一行不包含“删除”,我想打印一行。我使用的是Solaris 5.10,KSH。
答案1
和sed
:
sed '$!N;/remove/!P;D' infile
这会将N
ext 行拉入模式空间(如果不在!
la $
t 行上)并检查模式空间是否匹配remove
。如果不存在(意味着模式空间中的两行都不包含 string remove
),它将P
打印到第一个\n
ewline 字符(即打印第一行)。然后它D
删除第一个\n
ewline 字符并重新开始循环。这样,模式空间中的线永远不会超过两条。
如果在 之前和之后添加来查看模式空间,可能会更容易理解N
, P
,循环:D
l
N
sed 'l;$!N;l;/remove/!P;D' infile
因此,仅使用示例中的最后六行:
8AC3
remove
8AE4
8AE5
8AE6
remove
最后一个命令输出:
8AC3$ 8AC3\n 删除$ 删除$ 删除\n 8AE4$ 8AE4$ 8AE4\n 8AE5$ 8AE4 8AE5$ 8AE5\n 8AE6$ 8AE5 8AE6$ 8AE6\n 删除$ 删除$ 删除$
这是一个简短的解释:
cmd 输出 cmd
l 8AC3$ N # read in the next line
l 8AC3\n remove$ D # delete up to \n (pattern space matches so no P)
l remove$ N # read in the next line
l remove\n 8AE4$ D # delete up to \n (pattern space matches so no P)
l 8AE4$ N # read in the next line
l 8AE4\n 8AE5$ # pattern space doesn't match so print up to \n
P 8AE4 D # delete up to \n
l 8AE5$ N # read in the next line
l 8AE5\n 8AE6$ # pattern space doesn't match so print up to \n
P 8AE5 D # delete up to \n
l 8AE6$ N # read in the next line
l 8AE6\n remove$ D # delete up to \n (pattern space matches so no P)
l remove$ # last line so no N
l remove$ D # delete (pattern space matches so no P)
答案2
awk '
!/remove/ && NR > 1 && prev !~ /remove/ {print prev}
{prev = $0}
END {if (!/remove/) print}
' Input.txt
答案3
gawk 'BEGIN{ RS="remove\n"; ORS="" }
RT{ print gensub("[^\n]*\n$","","") }; !RT{ print }' file
上面的方法没有读取Records逐行,而是它读作多线从一个记录分隔符 (RS) 到下一个记录分隔符(或文件结尾)的记录 –RS
是“删除”行本身(包括其尾部 `\n)。
!RT
当最后一行不是一行时需要进行测试RS
。
RT
, A傻瓜主义,是当前记录的实际文本RS
。
gensub
也是一个傻瓜主义。
如果您需要检查标记线火柴“删除”行中的任何位置,而不是一行等于“删除”,然后只需将记录分隔符更改为:
`RS="[^\n]*remove[^\n]*\n"`
输出:
8B0F
8AC0
8AE4
8AE5