有没有一种方法可以使用sed仅删除完全匹配的字符串?

时间:2019-01-11 09:12:10

标签: sed

我最近开始学习bash,在做作业时遇到问题,所以我有一个txt文件,其中包含类似

的内容
foo:abc:200:1:1:1
foobar:asd:100:3:2:1
bar:test:100:2:2:2

其中第一列是书名,其次是作者名称,其次是价格,可用数量和已售数量,均用定界符“:”分隔

这里的目标是删除基于该书名的书,并作者输入用户。

我四处搜索,发现sed也许可以帮助我解决这个问题,我尝试通过

删除仅基于标题的内容来测试sed。
sed /"foo"/d Book.txt

我希望输出是

foobar:asd:100:3:2:1
bar:test:100:2:2:2

无论输出是

bar:test:100:2:2:2   

这告诉我txt文件中包含“ foo”的任何行都将被删除

因此,我想问一下

  1. 是否可以使用sed,所以它仅删除完全匹配项而不是包含foo的行?
  2. 有没有办法在sed中使用定界符,所以我可以同时使用title和author?
  3. 我应该使用sed以外的东西吗?

3 个答案:

答案 0 :(得分:2)

使用sed最好使用:

sed -E '/(^|:)foo(:|$)/d' file

foobar:asd:100:3:2:1
bar:test:100:2:2:2

确保foo之前是开始或:,之后是结尾或:

但是此数据更适合awk,因为数据用冒号分隔:

awk -F: '$1 != "foo"' file

答案 1 :(得分:1)

  
      
  1. 有什么方法可以使用sed,因此它只删除完全匹配项而不是包含foo的行吗?
  2.   

是的,对于给定的示例,如果您将搜索模式标记为与foo:完全匹配,则可以删除它。例如如果您在下面做

sed '/^foo:/d' file

模式^表示以foo开头的字符串,后跟与您的用例匹配的冒号:。假设foo只能是第一列的一部分

  
      
  1. 有没有办法在sed中使用定界符,所以我可以同时使用title和author?
  2.   
  3. 我应该使用sed以外的东西吗?
  4.   

如果您要处理的输入文件具有固定的定界符,例如:,则它永远不会构成有效列内容的一部分,然后使用awk / perl更适合,因为一旦设置了定界符,它们就可以轻松阅读文本。

例如,考虑一个如果您要更改一本名为foobar的特定书籍的第四列的数量名称,可以使用awk

awk -F: 'BEGIN { OFS = FS } $1 == "foobar" { $4 = 6 }1' input-file

要在命令行上方解码,'..'中的内容将保持不变,并直接传递给命令,这就是我们将内容用单引号引起来的原因。同样,其中的语句在shell上下文中也没有意义。

因此,-F:将输入字段分隔符设置为:,这是命令逐行读取文件时,第一行被分解为由:分隔的标记。第一列标记为$1,该列一直扩展到$NF,表示该行的最后一列。 BEGIN { OFS = FS }部分将输出字段分隔符分配为与输入相同的分隔符,即当:也写输出时,保留awk的分隔符。

在某种意义上,部分$1 == "foobar" { $4 = 6 }几乎是不言自明的,如果第一列包含引号内的字符串,请在{..}内执行操作,该操作将第四列的值设置为{{1 }}。 6{..}1的简写形式,它根据定义的输出字段/记录分隔符来重新构造行。

答案 2 :(得分:1)

这可能对您有用(GNU sed):

sed '/\<foo\>/d' file

sed '/\bfoo\b/d' file

第一个解决方案使用\<起始词和\>结束词。第二种解决方案使用\b字边界。

P.S。 \b的对偶是\B,因此要删除仅包含foobarfoobaz而不仅包含foo的行,请使用:

sed '/\bfoo\B/d' file