在保留格式的同时提取两个模式(包括)之间的字符串
Extract string between two patterns (inclusive) while conserving the format
我有一个格式如下的文件
cat test.txt
id1,PPLLTOMaaaaaaaaaaaJACK
id2,PPLRTOMbbbbbbbbbbbJACK
id3,PPLRTOMcccccccccccJACK
我正在尝试识别并打印 TOM
和 JACK
之间的字符串,包括这两个字符串,同时保持第一列 FS=,
期望的输出:
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK
到目前为止我已经试过了gsub
:
awk -F"," 'gsub(/.*TOM|JACK.*/,"",) && !_[[=12=]]++' test.txt > out.txt
并有以下输出
id1 aaaaaaaaaaa
id2 bbbbbbbbbbb
id3 ccccccccccc
如您所见,我越来越接近了,但无法在我的输出中包含 TOM
和 JACK
模式。另外我也失去了原来的 FS
。我做错了什么?
任何帮助将不胜感激。
您是要执行以下操作吗?
$ cat test.txt
id1,PPLLTOMaaaaaaaaaaaJACKABCD
id2,PPLRTOMbbbbbbbbbbbJACKDFCC
id3,PPLRTOMcccccccccccJACKSDER
$ cat test.txt | sed -e 's/,.*TOM/,TOM/g' | sed -e 's/JACK.*/JACK/g'
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK
$
只要 TOM 和 JACK 不重复,这应该可以工作。
使用捕获组来保存你想要保留的行的部分。这是使用 sed
的方法
sed 's/^\([^,]*,\).*\(TOM.*JACK\).*//' <test.txt > out.txt
您正在更改字段 (</code>),这会导致 awk 使用 <code>OFS
的值作为字段分隔符重建记录,因此在本例中将逗号更改为空格。
切勿将 _
用作变量名 - 使用没有意义的名称仅比使用具有错误含义的名称稍微好一点,只需选择一个有意义的名称,在这种情况下是 seen
但不知道您在这种情况下使用它时要做什么。
gsub()
和 sub()
不支持捕获组,因此您需要使用 match()
+substr()
:
$ awk 'BEGIN{FS=OFS=","} match(,/TOM.*JACK/){=substr(,RSTART,RLENGTH)} 1' file
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK
或者使用 GNU awk 作为第三个参数 match()
$ gawk 'BEGIN{FS=OFS=","} match(,/TOM.*JACK/,a){=a[0]} 1' file
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK
或 gensub()
:
$ gawk 'BEGIN{FS=OFS=","} {=gensub(/.*(TOM.*JACK).*/,"\1","",)} 1' file
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK
match()
和 gensub()
解决方案之间的主要区别在于,如果 TOM 在线上出现两次,它们的行为方式:
$ cat file
id1,PPLLfooTOMbarTOMaaaaaaaaaaaJACK
id2,PPLRTOMbbbbbbbbbbbJACKfooJACKbar
id3,PPLRfooTOMbarTOMcccccccccccJACKfooJACKbar
$
$ awk 'BEGIN{FS=OFS=","} match(,/TOM.*JACK/,a){=a[0]} 1' file
id1,TOMbarTOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACKfooJACK
id3,TOMbarTOMcccccccccccJACKfooJACK
$
$ awk 'BEGIN{FS=OFS=","} {=gensub(/.*(TOM.*JACK).*/,"\1","",)} 1' file
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACKfooJACK
id3,TOMcccccccccccJACKfooJACK
并且只是为了展示一种在第一个而不是最后一个 JACK 处停止的方法:
$ awk 'BEGIN{FS=OFS=","} match(,/TOM.*JACK/,a){=gensub(/(JACK).*/,"\1","",a[0])} 1' file
id1,TOMbarTOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMbarTOMcccccccccccJACK
sed 's/\(.*,\).*\(TOM.*JACK\).*//' <oldfile >newfile
输出:
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK
我有一个格式如下的文件
cat test.txt
id1,PPLLTOMaaaaaaaaaaaJACK
id2,PPLRTOMbbbbbbbbbbbJACK
id3,PPLRTOMcccccccccccJACK
我正在尝试识别并打印 TOM
和 JACK
之间的字符串,包括这两个字符串,同时保持第一列 FS=,
期望的输出:
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK
到目前为止我已经试过了gsub
:
awk -F"," 'gsub(/.*TOM|JACK.*/,"",) && !_[[=12=]]++' test.txt > out.txt
并有以下输出
id1 aaaaaaaaaaa
id2 bbbbbbbbbbb
id3 ccccccccccc
如您所见,我越来越接近了,但无法在我的输出中包含 TOM
和 JACK
模式。另外我也失去了原来的 FS
。我做错了什么?
任何帮助将不胜感激。
您是要执行以下操作吗?
$ cat test.txt
id1,PPLLTOMaaaaaaaaaaaJACKABCD
id2,PPLRTOMbbbbbbbbbbbJACKDFCC
id3,PPLRTOMcccccccccccJACKSDER
$ cat test.txt | sed -e 's/,.*TOM/,TOM/g' | sed -e 's/JACK.*/JACK/g'
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK
$
只要 TOM 和 JACK 不重复,这应该可以工作。
使用捕获组来保存你想要保留的行的部分。这是使用 sed
sed 's/^\([^,]*,\).*\(TOM.*JACK\).*//' <test.txt > out.txt
您正在更改字段 (</code>),这会导致 awk 使用 <code>OFS
的值作为字段分隔符重建记录,因此在本例中将逗号更改为空格。
切勿将 _
用作变量名 - 使用没有意义的名称仅比使用具有错误含义的名称稍微好一点,只需选择一个有意义的名称,在这种情况下是 seen
但不知道您在这种情况下使用它时要做什么。
gsub()
和 sub()
不支持捕获组,因此您需要使用 match()
+substr()
:
$ awk 'BEGIN{FS=OFS=","} match(,/TOM.*JACK/){=substr(,RSTART,RLENGTH)} 1' file
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK
或者使用 GNU awk 作为第三个参数 match()
$ gawk 'BEGIN{FS=OFS=","} match(,/TOM.*JACK/,a){=a[0]} 1' file
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK
或 gensub()
:
$ gawk 'BEGIN{FS=OFS=","} {=gensub(/.*(TOM.*JACK).*/,"\1","",)} 1' file
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK
match()
和 gensub()
解决方案之间的主要区别在于,如果 TOM 在线上出现两次,它们的行为方式:
$ cat file
id1,PPLLfooTOMbarTOMaaaaaaaaaaaJACK
id2,PPLRTOMbbbbbbbbbbbJACKfooJACKbar
id3,PPLRfooTOMbarTOMcccccccccccJACKfooJACKbar
$
$ awk 'BEGIN{FS=OFS=","} match(,/TOM.*JACK/,a){=a[0]} 1' file
id1,TOMbarTOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACKfooJACK
id3,TOMbarTOMcccccccccccJACKfooJACK
$
$ awk 'BEGIN{FS=OFS=","} {=gensub(/.*(TOM.*JACK).*/,"\1","",)} 1' file
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACKfooJACK
id3,TOMcccccccccccJACKfooJACK
并且只是为了展示一种在第一个而不是最后一个 JACK 处停止的方法:
$ awk 'BEGIN{FS=OFS=","} match(,/TOM.*JACK/,a){=gensub(/(JACK).*/,"\1","",a[0])} 1' file
id1,TOMbarTOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMbarTOMcccccccccccJACK
sed 's/\(.*,\).*\(TOM.*JACK\).*//' <oldfile >newfile
输出:
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK