【问题标题】:Is there a way to use sed to remove only the exact string match?有没有办法使用 sed 只删除完全匹配的字符串?
【发布时间】:2020-06-26 02:57:26
【问题描述】:

我最近开始学习 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 中使用分隔符,以便我可以同时使用标题和作者?
  3. 我应该使用 sed 以外的东西吗?

【问题讨论】:

标签: regex sed


【解决方案1】:

使用sed更好用:

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

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

这确保foo 前面是 start 或 :,后面是 end 或 :

但是这个工作更适合awk,因为数据是用冒号分隔的:

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

【讨论】:

    【解决方案2】:
    1. 有什么方法可以使用sed,所以它只删除完全匹配而不是包含 foo 的行?

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

    sed '/^foo:/d' file
    

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

    1. 有什么方法可以在 sed 中使用分隔符,以便我可以同时使用标题和作者?
    2. 我应该使用 sed 以外的东西吗?

    如果您正在处理的输入文件有一个固定的分隔符,例如:,它永远不会构成您的有效列内容的一部分,那么使用awk/perl 是更适合,因为一旦设置了分隔符,他们就可以轻松阅读文本。

    例如,考虑一个例子。如果您想更改名为foobar 的特定书籍的第四列的数量名称,使用awk 您可以这样做

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

    要解码上面的行,'..' 中的内容不会被 shell 修改并按字面意思传递给命令,这就是我们将内容用单引号括起来的原因。此外,其中的语句在 shell 的上下文中也没有意义。

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

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

    【讨论】:

      【解决方案3】:

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

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

      或者

      sed '/\bfoo\b/d' file
      

      第一个解决方案使用\&lt; 起始字和\&gt; 结束字。第二种解决方案使用\b 字边界。

      附: \b 的对偶是 \B,因此要删除包含 foobarfoobaz 但不包含 foo 的行,请使用:

      sed '/\bfoo\B/d' file
      

      【讨论】:

        猜你喜欢
        • 2019-11-13
        • 2015-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-20
        • 2019-08-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多