【问题标题】:How to remove a word prefix using grep?如何使用 grep 删除单词前缀?
【发布时间】:2012-07-25 06:36:12
【问题描述】:

如何使用 grep 删除单词的开头?例如:我有一个文件包含:

www.abc.com

我只需要部分

abc.com

对不起,基本问题。但是没有使用 Linux 的经验。

【问题讨论】:

  • 使用sed 代替grep。

标签: regex linux shell sed


【解决方案1】:

您不能在 Unix shell 中使用 grep 编辑字符串,grep 通常用于从文本中查找或删除某些行。您宁愿使用sed

$ echo www.example.com | sed 's/^[^\.]\+\.//'
example.com

你需要学习正则表达式to use it effectively

Sed 也可以就地编辑文件(修改文件),如果你传递-i 参数,但要小心,如果你写了错误的sed 命令并使用-i 标志,你很容易丢失数据。

一个例子

从您的 cmets 猜测您有一个 TeX 文档,并且您想删除所有 .com 域名的第一部分。如果是你的文档test.tex

\documentclass{article}
\begin{document}
www.example.com
example.com www.another.domain.com
\end{document}

然后您可以使用此sed 命令对其进行转换(将输出重定向到文件或使用-i 就地编辑):

$ sed 's/\([a-z0-9-]\+\.\)\(\([a-z0-9-]\+\.\)\+com\)/\2/gi' test.tex 
\documentclass{article}
\begin{document}
example.com
example.com another.domain.com
\end{document}

请注意:

  • 允许符号的公共序列后跟一个点与[a-z0-9-]\+\. 匹配
  • 我在正则表达式中使用了组(\(\) 中的部分)来指示 URL 的第一和第二部分,并将整个匹配替换为其第二组(\2 in替换模式)
  • 域应至少是第 3 级 .com 域(每个 \+ 重复意味着至少一个匹配项)
  • 搜索不区分大小写(最后是i 标志)
  • 它可以做的不仅仅是每行匹配(g 标志在最后)

【讨论】:

  • 网址保存在一个文件中。所以我的命令是: grep'\.com$' source.text >dest.tex | sed 's/^[^\.]\+\.//' ??它给了我错误??
  • 删除 www 后,我还需要在另一个文本文件中写入名称(它们是多行而不是一行)。
  • 我试图猜测您的任务是什么,并编写了一个 sed 正则表达式示例来编辑文档中的域名,而没有触及其余行。如果您的问题不同,您可能需要不同的正则表达式,但总体思路是相同的。
  • 通常您要么重定向到文件 (> dest.tex),要么只使用管道 (| sed ...),但不能同时使用两者。如果您想更改某些行但保留其余行,则不需要grep。一个精心编写的正则表达式和sed 可能就是您所需要的。
  • 在 macOS 上,sed 命令的工作方式与 Linux 版本不同。但是您可以在 Mac 上使用这个更简单的版本,无需正则表达式:echo www.example.com | sed "s/www.//" -- 它将用空字符串 "" 替换 "www."
【解决方案2】:

您可以使用grep 轻松做到这一点:

$ echo www.google.com | grep -o '[^.]*\.com'
google.com

您必须提供您的文件,而不是 echo

$ grep -o '[^.]*\.com$' < file

我在这里使用了正则表达式“[^.]*.com”。这意味着:给我找一个没有. 的词([^.]*),然后是.com(回复\.com)。 -o 键表示 grep 必须只显示找到的部分。

【讨论】:

    【解决方案3】:

    正如其他人所指出的,grep 不太适合此任务,sed 是一个不错的选择,或者如果文本井井有条,则简单的cut 可能更容易输入:

    echo www.abc.com | cut -d. -f2-
    
    • -d. 告诉 cut 使用 . 作为分隔符。
    • -f2- 告诉 cut 将字段 2 返回到无穷大。

    【讨论】:

      【解决方案4】:

      使用 grep 的 --only-matching\K

      您可以使用 grep 的 --only-matching 标志来做到这一点:

      echo "www.abc.com" | grep --perl-regexp --only-matching 'www.\K.*'
      

      可以简写为

      echo "www.abc.com" | grep -Po 'www.\K.*'
      

      两个命令都产生

      abc.com

      使用 grep (GNU grep) 3.3。

      我将使用here string 代替echo 来进一步缩短命令:

      grep -Po 'www.\K.*' <<< "www.abc.com"
      

      \K 重置匹配的起点,基本上忘记了匹配的“www.”。有关\K 的更多信息,请参阅this

      与 grep 的积极后视

      您也可以使用positive lookbehind

      grep -Po '(?<=www.).*' <<< "www.abc.com"
      

      带有 awk 的字段分隔符 -F

      awk -F 'www.' <<< "www.abc.com" '$2{print $2}'
      

      打印出来

      abc.com

      $2{print $2} 部分将打印第二个字段(如果已定义)。这在多行输入的情况下是必要的,以避免为不包含字段分隔符的输入行输出空行。

      【讨论】:

        【解决方案5】:

        grep 不用于操作/更改文本,仅用于搜索文本中的文本/模式

        如果您想要一个命令行工具来执行此操作,您应该查看类似 sedawkcut 的内容。或者用 Python/Perl/Ruby/whatever 写一个脚本。

        【讨论】:

          【解决方案6】:

          您实际上可以在不调用其他程序的情况下执行此操作,方法是在 bash 中使用内置参数扩展:

          while read line; do echo ${line#*.}; done < file
          

          #*. 告诉 shell 删除看起来像 0 个或多个字符后跟 . 的前缀。

          您可以在此处查看带有不同参数扩展的 bash 备忘单:

          https://devhints.io/bash

          【讨论】:

            猜你喜欢
            • 2017-01-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多