Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 在保留格式的同时提取两个模式(包括)之间的字符串_Bash_Shell_Awk_Gsub - Fatal编程技术网

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

Bash 在保留格式的同时提取两个模式(包括)之间的字符串,bash,shell,awk,gsub,Bash,Shell,Awk,Gsub,我有一个以下格式的文件 cat test.txt id1,PPLLTOMaaaaaaaaaaaJACK id2,PPLRTOMbbbbbbbbbbbJACK id3,PPLRTOMcccccccccccJACK 我试图识别并打印TOM和JACK之间的字符串,包括这两个字符串,同时维护第一列FS=, 期望输出: id1,TOMaaaaaaaaaaaJACK id2,TOMbbbbbbbbbbbJACK id3,TOMcccccccccccJACK 到目前为止,我已经尝试了gsub: awk -

我有一个以下格式的文件

cat test.txt
id1,PPLLTOMaaaaaaaaaaaJACK
id2,PPLRTOMbbbbbbbbbbbJACK
id3,PPLRTOMcccccccccccJACK
我试图识别并打印
TOM
JACK
之间的字符串,包括这两个字符串,同时维护第一列
FS=,

期望输出:

id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK
到目前为止,我已经尝试了
gsub

awk -F"," 'gsub(/.*TOM|JACK.*/,"",$2) && !_[$0]++' test.txt > out.txt
$ gawk 'BEGIN{FS=OFS=","} {$2=gensub(/.*(TOM.*JACK).*/,"\\1","",$2)} 1' file
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK
并具有以下输出

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\).*/\1\2/' <test.txt > out.txt
sed的/^\([^,]*,\).\(TOM.*JACK\)./\1\2/'out.txt
您正在更改一个字段(
$2
),这会导致awk使用
OFS
的值作为字段分隔符来重建记录,因此在本例中,将逗号更改为空格

永远不要将
\uuuu
用作变量名-使用没有意义的名称要比使用有错误意义的名称稍微好一点,只需选择一个具有某种含义的名称,在本例中是
所见的
,但请确定在本上下文中使用该名称时要做什么

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

或者对第三个参数使用GNU awk来
match()

或对于
gensub()

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
$ awk 'BEGIN{FS=OFS=","} match($2,/TOM.*JACK/,a){$2=gensub(/(JACK).*/,"\\1","",a[0])} 1' file
id1,TOMbarTOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMbarTOMcccccccccccJACK
只是为了展示一种在第一个而不是最后一个插孔处停车的方法:

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

如果一行中包含
TOMabcBOB
,则可能会出现不希望出现的情况。只要TOM和JACK在预期的位置存在,这应该可以工作。什么可能不起作用的示例?像
id,fooTOMabcBOB
这样的行,如果它可以存在于输入中,则会被不希望地更改为
id,tomabcb
。我也不这样做,但它阻止了我在awk答案中使用类似的解决方案:-)。
sed 's/\(.*,\).*\(TOM.*JACK\).*/\1\2/' <oldfile >newfile
id1,TOMaaaaaaaaaaaJACK
id2,TOMbbbbbbbbbbbJACK
id3,TOMcccccccccccJACK