“sed”与模式不匹配

Posted

技术标签:

【中文标题】“sed”与模式不匹配【英文标题】:"sed" doesn't match pattern 【发布时间】:2021-05-23 02:18:08 【问题描述】:

我正在尝试格式化剪切、粘贴输出,但 sed 不起作用。

文件.txt

Apple
Banana
Apple
Banana
Orange
Apple
Orange

code.sh

cut -f2 file.txt | sort | uniq | sed 's/^\|$/#/g'| paste -sd,\& -

ubuntu 上的预期输出/输出

#Apple#,#Banana#&#Orange#

在 macOS 上获取输出/输出

Apple,Banana&Orange

注意:代码可在 Ubuntu 上运行,但在 MacOS 上则不行。

【问题讨论】:

仅供参考,您可以将 sort | uniq 组合到 sort -u macos sed 可能不支持\|.. 你可以试试sed -E 's/^|$/#/g' 另见:***.com/questions/24275070/… 此问题与cutsortuniqpaste无关。您可以将整个示例简化为 echo foo | sed 's/^\|$/#/g' @Sundeep 很奇怪,在每行的开头插入#,而不是结尾。 为什么是cut -f2?该文件只有一个字段。 【参考方案1】:

这可以在单个gnu-awk 中完成:

awk '!seen[$1]++ END 
    PROCINFO["sorted_in"]="@ind_str_asc"
    for (i in seen)
      s = s (s == "" ? "" : (++j==1?",":"&")) "#" i "#"
    print s
' file

#Apple#,#Banana#&#Orange#

在 OSX 上,我通过 home brew 安装了 gnu awk

【讨论】:

看起来不错,我有自制的,但我不使用 awk。 安装超级简单然后brew install gawk【参考方案2】:

正如在别处提到的,BSD sed 不支持 \|。除了替换^$,您可以替换#围绕整行。

sort -u file.txt | sed 's/.*/#&#/' | paste -sd,'&' -

【讨论】:

感谢sort -u,但它适用于 ubuntu 吗? 它应该适用于任何地方,它是标准的sort 选项,早于所有不同风格的 Unix。 我意识到您的解决方案工作正常,但请告诉我一件事,为什么您在 s/.*/#&#/ 中将 $ 替换为 &。使用 $ 不起作用。 & 被替换为任何匹配的正则表达式,即整行。 对,-u 是 POSIX sort 的必需参数,请参阅 pubs.opengroup.org/onlinepubs/9699919799/utilities/sort.html,并且在我记得过去 40 多年中使用的所有类型中都存在。【参考方案3】:

据我所知,BSD/Mac sed 不支持 \|。详情请见sed not giving me correct substitute operation for newline with Mac - differences between GNU sed and BSD / OSX sed。

作为替代方案,您可以使用 ERE 代替 BRE。我在 Linux 上检查过,显然这在 Mac 上似乎仍然不起作用(另见:MacOS sed: match either beginning or end)。

$ echo 'Apple' | sed -E 's/^|$/#/g'
#Apple#

# workaround for Mac
$ echo 'Apple' | sed -e 's/^/#/' -e 's/$/#/'
#Apple#

除了sort+uniq+sed,您还可以使用awk(但请注意,此处显示的awk 解决方案会在保留原始顺序的同时删除重复项,而不是sort 输入):

$ awk '!seen[$0]++print "#" $0 "#"' ip.txt
#Apple#
#Banana#
#Orange#

如果您只需要第二个字段,请将$0 更改为$2,具体取决于您对cut 的使用

【讨论】:

可能取决于操作系统版本,但在 10.13.6 上,sed 命令仅生成 #Apple @Barmar 我只有 Linux,所以无法在其他地方进行测试。编辑答案以反映这一点。 Sundeep 和 @Barmar - 请参阅 superuser.com/a/1420167,您遇到了 MacOS 上 sed 中的 s/^|$/#/g 错误。 好找到@EdMorton @Barmar,谢谢。我敢肯定还有其他提供 C&V 的帖子,因为我以前遇到过这个,我只是懒得去寻找它们!【参考方案4】:

使用 sed 命令的简单方法:

sed -E 's/[[:alnum:]]+/#&#/'
用于启用 POSIX ERE 的 -E 选项(扩展常规 表达) [[:alnum:]]+ 字母数字字符;在 ASCII 中,相当于 [A-Za-z0-9] 加上加号 (+) 表示一个或多个。 & 符号确实带来或引用了我们发现的模式的内容。 (我们用#包围它)

【讨论】:

以上是关于“sed”与模式不匹配的主要内容,如果未能解决你的问题,请参考以下文章

如果一行匹配条件,则 sed 替换与模式范围匹配的行

awk / sed:如果任何字段与模式匹配,则替换所有字段

三剑客之sed

当一行与模式匹配时,我可以在sed中执行两个命令吗?

linux学习--grep与sed

使用 sed 或 awk 按照匹配模式打印一行