在多个块中的某些模式之间替换任何字符

时间:2019-07-22 17:45:18

标签: bash awk sed

我遇到的问题类似于this,但我无法适应我的情况。

说我有一个包含以下许多行的文件:

f  1/1/519 2/2/2 3/3/520
f  287/4/521 1/5/519 3/6/520
f  5/7/522 1/8/523 287/9/524

我要替换每个块的两个斜杠(number/anyNumber/number)之间的内容。

我希望得到以下结果:

f  1//519 2//2 3//520
f  287//521 1//519 3//520
f  5//522 1//523 287//524

正确的sed(或其他任何命令)命令是什么?

使用MacOS。

4 个答案:

答案 0 :(得分:2)

$ sed 's:/[^/]*/://:g' file
f  1//519 2//2 3//520
f  287//521 1//519 3//520
f  5//522 1//523 287//524

答案 1 :(得分:1)

请您尝试以下。

awk '{for(i=1;i<=NF;i++){gsub(/\/.*\//,"//",$i)}} 1'   Input_file

输出如下。

f 1//519 2//2 3//520
f 287//521 1//519 3//520
f 5//522 1//523 287//524

答案 2 :(得分:1)

在sed中基于此模式轻松实现

sed 's#/[0-9]*/#//#g' input.txt

这匹配两个斜杠之间的零个或多个数字的任何延伸,并用两个斜杠替换整个捆绑包。

在awk中,您可能会通过以下方式执行相同的操作:

awk '{gsub(/\/[0-9]*\//,"//")} 1' input.txt

gsub()命令记录在awk手册页上。最后的1是“打印此行”的快捷方式。但是您也可以将这些字段视为实际字段:

awk '{for (i=2;i<=NF;i++) {split($i,a,"/"); $i=sprintf("%s//%s",a[1],a[3])} } 1' input.txt

这在技术上是“正确的”,因为它将字段视为字段,然后将子字段视为子字段。但这无疑比其他选项要慢,并且还将重写使用OFS作为字段分隔符的行。

最后,您可以单独使用bash,而无需awk或sed:

shopt -s extglob
while read; do echo "${REPLY//\/+([0-9])\////}"; done < input.txt

这在bash版本3中有效(因为您使用的是macOS)。它读取输入的每一行,然后使用参数扩展来进行与前两个选项相同的转换。此解决方案可能比其他解决方案慢。 extglob shell选项用于使更多高级模式成为可能。

答案 3 :(得分:0)

答案很简单:cat file.txt | sed -e 's/\([0-9]\+\/\)[0-9]\+\(\/[0-9]\+\)/\1\2/g' > mod.txt

将一些内容放在方括号(())中,可以稍后使用它,即记住第一个斜杠之前的数字加上斜杠(第一个捕获组),在两个斜杠之间匹配数字,然后记住斜杠和斜线(第二个捕获组)之后的任何数字,则只需将整个匹配的字符串替换为第一个和第二个捕获组,就丢弃所有其他内容。

使用g开关使sed在每次匹配的情况下运行。