Unix 从管道分隔文件中的字符串中删除不匹配的值
我有一个输入文件,其中的列由Unix 从管道分隔文件中的字符串中删除不匹配的值,unix,awk,Unix,Awk,我有一个输入文件,其中的列由| 输入文件: COL1|COL2 CRIC1|IPL_M1;IPL_M2;TEST_M1 CRIC2|ODI_M1;IPL_M3 CRIC3|ODI_M3;TEST_M5 CRIC4|IPL_M5;ODI_M5;IPL_M;RANGI_M1 CRIC5|RANGI_M1 输出应仅在COL2中更改,其他列不应更改,即在COL2中,应填充具有“IPL_”的字符串, 除“IPL”之外,还需要填充为null并删除不需要的分号。COL2可能包含多达个值(IPL和非IPL值)
|
输入文件:
COL1|COL2
CRIC1|IPL_M1;IPL_M2;TEST_M1
CRIC2|ODI_M1;IPL_M3
CRIC3|ODI_M3;TEST_M5
CRIC4|IPL_M5;ODI_M5;IPL_M;RANGI_M1
CRIC5|RANGI_M1
输出应仅在COL2中更改,其他列不应更改,即在COL2中,应填充具有“IPL_”的字符串,
除“IPL”之外,还需要填充为null并删除不需要的分号。COL2可能包含多达个值(IPL和非IPL值)
预期产出:
COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M6
CRIC5|
我试过这个:
awk -F, -vOFS="|" '{$2=($2!="IPL_%")?" ":$2}1' File.txt
Awk
解决方案:
awk 'BEGIN{ FS = OFS = "|" }
NR == 1;
NR > 1{
len = split($2, a, ";");
res = "";
for (i = 1; i <= len; i++)
if (a[i] ~ /^IPL_/) res = res (res != ""? ";" : "") a[i];
print $1, res
}' file.txt
由于所有很酷的awk答案都已被采纳,我开始使用PCRE lookaround,因此,如果您可以使用perl,这里有一个:
perl -p -e 's/(?<=(\|)|(;))[^I][^P][^L][^;\n]*(;|(\n))|/\4/g if $.>1;s/;$//' file
COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M
CRIC5|
输出
COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M # fails if <3 preceeds a match
CRIC5|
$awk'
开始{FS=OFS=“|”;sfs=“;”}
NR>1{
n=拆分(2美元,f,sfs)
$2 = ""
对于(i=1;i如果perl
正常:
$ perl -F'\|' -lane '$F[1] = join ";", grep {/IPL_/} split /;/,$F[1] if $.>1;
print join "|", @F' ip.txt
COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M
CRIC5|
-F'\\'-lane
有关详细信息,请参见。此处,
设置为输入字段分隔符,结果可从@F
数组中获得
如果$.>1
如果输入行号大于1
split/;/,$F[1]
在;
grep{/IPL\/}
仅从拆分输出中筛选包含IPL\
的元素。如果需要,请使用正则表达式锚定
join”;“
使用;
连接grep
的输出,然后将结果保存回@F
数组的第二个元素
打印联接“|”、@F
,然后打印@F
数组的元素,并使用
作为分隔符
带有sed
sed -E '
1b
s/\|/\|;/
s/IPL_M/@/g
s/;[^@][^;]*//g
s/\|;/\|/
s/@/IPL_M/g
' infile
另一种awk
变体:
awk -F '|' '
NR == 1 { print; next }
{
split($2, a, ";")
s = ""
for (i = 1; i <= length(a); ++i)
if (a[i] ~ /^IPL_/)
s = s a[i] ";"
print $1, substr(s, 1, length(s)-1)
}' OFS='|' file
你试过什么吗?试过一个,但不起作用awk-F,-vOFS=“|”“{$2=($2!=“IPL%”)”?“:$2}1”File.txt
在你的问题中包括你的尝试,并说明它“不起作用”的方式。稍后要发表评论,紧急情况在手。如果你在第二栏中的字段少于3个字符怎么办?)@Sundeep失败。您可以将其简化为perl-lpe的/(?1;s/;$/”
,但我仍然认为这并不可靠。无论如何,欢迎来到perl世界:D
$ awk '
BEGIN{ FS=OFS="|" }
{
n=split($2,a,";")
for(i=1;i<=n;i++)
if(a[i]~/^IPL/||NR==1)
b=b (b==""?"":";") a[i]
print $1,b;b=""
}' file
COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M
CRIC5|
$ awk '
BEGIN { FS=OFS="|"; sfs=";" }
NR>1 {
n = split($2,f,sfs)
$2 = ""
for (i=1; i<=n; i++) {
if (f[i] ~ /^IPL_/) {
$2 = ($2=="" ? "" : $2 sfs) f[i]
}
}
}
{ print }
' file
COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M
CRIC5|
$ perl -F'\|' -lane '$F[1] = join ";", grep {/IPL_/} split /;/,$F[1] if $.>1;
print join "|", @F' ip.txt
COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M
CRIC5|
sed -E '
1b
s/\|/\|;/
s/IPL_M/@/g
s/;[^@][^;]*//g
s/\|;/\|/
s/@/IPL_M/g
' infile
awk -F '|' '
NR == 1 { print; next }
{
split($2, a, ";")
s = ""
for (i = 1; i <= length(a); ++i)
if (a[i] ~ /^IPL_/)
s = s a[i] ";"
print $1, substr(s, 1, length(s)-1)
}' OFS='|' file
COL1|COL2
CRIC1|IPL_M1;IPL_M2
CRIC2|IPL_M3
CRIC3|
CRIC4|IPL_M5;IPL_M
CRIC5|