bash - 在保留格式的同时提取两个模式(包括)之间的字符串

标签 bash shell awk gsub

我有一个如下格式的文件

cat test.txt
id1,PPLLTOMaaaaaaaaaaaJACK
id2,PPLRTOMbbbbbbbbbbbJACK
id3,PPLRTOMcccccccccccJACK

我正在尝试识别并打印 TOMJACK 之间的字符串,包括这两个字符串,同时保持第一列 FS=,

期望的输出:

id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK

到目前为止,我已经尝试过 gsub:

awk -F"," 'gsub(/.*TOM|JACK.*/,"",$2) && !_[$0]++' test.txt > out.txt

并有以下输出

id1 aaaaaaaaaaa
id2 bbbbbbbbbbb
id3 ccccccccccc

如您所见,我越来越接近了,但无法在我的输出中包含 TOMJACK 模式。另外,我还丢失了原始的 FS。我做错了什么?

我们将不胜感激。

最佳答案

您正在更改一个字段 ($2),这会导致 awk 使用 OFS 的值作为字段分隔符来重建记录,因此在本例中将逗号更改为空格。

切勿将 _ 用作变量名 - 使用没有意义的名称比使用具有错误含义的名称稍微好一点,只需选择一个有意义的名称,在这种情况下是看到了,但不知道您在这种情况下使用它时要尝试做什么。

gsub()sub() 不支持捕获组,因此您需要使用 match()+substr ():

$ awk 'BEGIN{FS=OFS=","} match($2,/TOM.*JACK/){$2=substr($2,RSTART,RLENGTH)} 1' file
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK

或者使用 GNU awk 作为 match()

的第三个参数
$ gawk 'BEGIN{FS=OFS=","} match($2,/TOM.*JACK/,a){$2=a[0]} 1' file
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK

或者对于gensub():

$ gawk 'BEGIN{FS=OFS=","} {$2=gensub(/.*(TOM.*JACK).*/,"\\1","",$2)} 1' file
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK

match()gensub() 解决方案之间的主要区别在于,如果 TOM 在线上出现两次,它们将如何表现:

$ cat file
id1,PPLLfooTOMbarTOMaaaaaaaaaaaJACK
id2,PPLRTOMbbbbbbbbbbbJACKfooJACKbar
id3,PPLRfooTOMbarTOMcccccccccccJACKfooJACKbar
$
$ awk 'BEGIN{FS=OFS=","} match($2,/TOM.*JACK/,a){$2=a[0]} 1' file
id1,TOMbarTOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACKfooJACK
id3,TOMbarTOMcccccccccccJACKfooJACK
$
$ awk 'BEGIN{FS=OFS=","} {$2=gensub(/.*(TOM.*JACK).*/,"\\1","",$2)} 1' file
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACKfooJACK
id3,TOMcccccccccccJACKfooJACK

只是为了展示一种在第一个而不是最后一个 JACK 处停止的方法:

$ awk 'BEGIN{FS=OFS=","} match($2,/TOM.*JACK/,a){$2=gensub(/(JACK).*/,"\\1","",a[0])} 1' file
id1,TOMbarTOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMbarTOMcccccccccccJACK

关于bash - 在保留格式的同时提取两个模式(包括)之间的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30041955/

相关文章:

用于查找最近修改的文件的 Bash 脚本

shell - 如何根据ubuntu中的内容删除多个文件

linux - 使用 awk 比较 2 个文件 - 如果第二个字段相同,则对第一个字段求​​和并打印它 - 如果不打印它(对于两个文件中的不匹配条目为 true)

wordpress - 使用 AWK 安全地搜索和替换 Wordpress SQL-Dump 中的 URL

bash - 为什么 Bash 在与 Curl 一起使用时不会等待读取?

linux - 如何在 git 或 shell 别名中使用 `find -exec sh -c`

windows - FFMPEG 的输入参数

linux - 在 awk 命令中使用 BASH 整数变量

linux - 如何比较bash中的2个范围列表?

c - c 中的 shell 未按预期工作 - 与管道损坏相关