您好:我有表格的分页数据 客户项目描述 - 购买价格 - 类别
e.g。 a.out包含:
1\t400 Bananas\t3.00\tfruit 2\t60 Oranges\t0.00\tfruit 3\tNULL\t3.0\tfruit 4\tCarrots\tNULL\tfruit 5\tNULL\tNULL\tfruit
我试图摆脱所有的NULL字段。我不能依赖于字符串“NULL”的简单替换,因为它可能是一个子字符串;所以我正在尝试
sed -i 's:\tNULL\t:\t\t:g' a.out
当我这样做时,我最终会
1\t400 Bananas\t3.00\tfruit 2\t60 Oranges\t0.00\tfruit 3\t\t3.0\tfruit 4\tCarrots\t\tfruit 5.\t\tNULL\tfruit
这里的错误是#5只在每一行上替换了第一个搜索字符串实例。
如果我两次运行我的sed命令,我最终会得到我想要的结果:
1\t400 Bananas\t3.00\tfruit 2\t60 Oranges\t0.00\tfruit 3\t\t3.0\tfruit 4\tCarrots\t\tfruit 5.\t\t\tfruit
您可以看到第5行删除了两个NULL 但是我不明白我为什么要这么痛苦?
答案 0 :(得分:3)
由于标签不能出现在您的案例中的字符串内,因为这意味着您可以通过执行此操作来实现您想要的新字段;
sed ':start ; s/\tNULL\(\t\|$\)/\t\1/ ; t start' a.out
首先,内部s/\tNULL\(\t\|$\)/\t\1/
搜索tab
NULL
,然后搜索tab
或行尾$
,并替换为tab
然后是NULL
之后出现的字符(最后一部分是使用\1
完成的)。我们称之为expression
我们现在有:
sed ':start ; expression ; t start' a.out
这实际上是一个循环(如goto)。 :start是一个标签。 ;
充当语句分隔符。我已经描述了上面的表达式。 t start
表示,如果表达式做了任何替换,则会跳转到标签start
。缓冲区将包含替换文本。发生此循环直到无法在该行上进行替换,然后继续处理。
有关sed流量控制和其他有用花絮的信息可以找到here
答案 1 :(得分:3)
awk -F'\t' -v OFS='\t' '{
for (i = 1; i <= NF; ++i) {
if ($i == "NULL") {
$i = "";
}
}
print
}' test.txt
直接的解决方案是使用\t
作为字段分隔符,然后遍历所有字段以查找"NULL"
的完全匹配。没有子串。
这里和一个班轮一样:
awk -F'\t' -v OFS='\t' '{for(i=1;i<=NF;++i) if($i=="NULL") $i=""} 1' test.txt
答案 2 :(得分:0)
awk
简化了:
awk -F '\tNULL\\>' -v OFS='\t' '{$1=$1}1' file
1\t400 Bananas\t3.00\tfruit
2\t60 Oranges\t0.00\tfruit
3\t\t3.0\tfruit
4\tCarrots\t\tfruit
5\t\t\tfruit
答案 3 :(得分:0)
来自最近的Linux上的grep(1)
:
反斜杠字符和特殊表达
符号\&lt;和&gt;分别匹配空字符串 一个词的开头和结尾。符号\ b与空字符串匹配 一个词的边缘[...]
-
那么,怎么样:
sed -i 's:\<NULL\>::g' a.out