Awk 删除记录中重复的字段
Awk 删除记录中重复的字段,awk,Awk,在此处输入code我想删除每条记录中键的重复实例(前两个字段)。在我看来,复制品实际上是反向的 如此给定 a b b a stuff1 b a stuff2 stuff3 b a 其中每个空格都是一个选项卡 我想: a b stuff1 stuff2 stuff3 我想这样就行了: awk 'BEGIN {FS=OFS="\t"} {gsub($2 "\t" $1,"")} 1' file 欢迎使用其他解决方案,但我特别感兴趣的是为什么这不起作用 (我用一个动态reg
在此处输入code
我想删除每条记录中键的重复实例(前两个字段)。在我看来,复制品实际上是反向的
如此给定
a b b a stuff1 b a stuff2 stuff3 b a
其中每个空格都是一个选项卡
我想:
a b stuff1 stuff2 stuff3
我想这样就行了:
awk 'BEGIN {FS=OFS="\t"}
{gsub($2 "\t" $1,"")}
1' file
欢迎使用其他解决方案,但我特别感兴趣的是为什么这不起作用(我用一个动态regexp和
gensub
btw进行了尝试)
根据前面的问题,我知道我可能/将以重复选项卡结束,并将在awk
之外处理该问题
编辑
到目前为止,解决方案不起作用,所以这里是真实的数据。对于^read,读取制表符
1874 ^Passage de Venus^ <DIRECTORS> ^Passage de Venus^ 1874^ Janssen, P.J.C.^ <keywords>^ Passage de Venus^ 1874^ astronomy^ astrophotography^ <genres>^ Short
1874^金星之路^金星之路^ 1874^杨森,P.J.C.^金星之路^ 1874^天文学^天体摄影^简称
我想要的是
1874^ Passage de Venus^ <DIRECTORS>^ Janssen, P.J.C.^ <keywords>^ astronomy^ astrophotography^ <genres>^ Short
1874^维纳斯之路^杨森,P.J.C.^天文学^天体摄影^简称
我能想到的唯一问题是输入文件没有用制表符分隔
测试
$ echo "a b b a stuff1 b a stuff2 stuff3 b a" | awk '{gsub($2" "$1,"")}1'
a b stuff1 stuff2 stuff3
您的尝试很好,您可能在空格/制表符方面遇到了一些问题。此外,您可能希望使用
FS
使其更易更改:
awk 'BEGIN {FS=OFS="\t"} {gsub($2 FS $1, "")}1' file
|____________________^
因此,如果您注意到字段分隔符是另一个,只需在BEGIN
块中更改它,它就会正常工作
试验
你可以试试这个
awk '{gsub($2 "[[:space:]]+" $1, "")}1' file
如果这样做有效并且使用“\t”
不起作用,那么您可能没有使用选项卡
再次检查没有错误,很可能您的文件中的选项卡旁边有空间
试一试
虽然这个答案纯粹是为了排除gsub不起作用的原因,但我已决定在评论中添加此附录,以解决Eds问题
这将停止匹配除$2
之外的单词,然后再匹配$1
,并且还应清理格式混乱
awk 'BEGIN{FS=" *\t *"}{$0=gensub("("FS")" $2 FS $1 "("FS")","\\1","g")}1' file
例子
即使使用metachars,它也应该更加健壮
awk -F' *\t *' '{x=y;for(i=1;i<=NF;i++)(i>2&&$i==$2&&$(i+1)==$1&&i++)||x=x?x"\t"$i:$i;$0=x}1' file
awk-F'*\t*'{x=y;对于(i=1;i2&&$i==$2&&$(i+1)=$1&&i++)| x=x?x“\t”$i:$i;$0=x}1”文件
这是您真正需要的解决方案,因为它对完整字段进行字符串比较,因此当字段包含重元字符或字段以与$1/$2相同的值开始或结束时,不会出现错误匹配:
awk -F' *\t *' -v OFS='\t' '{
rec = $1 OFS $2
for (i=3; i<=NF; i++) {
if ( ($i == $2) && ($(i+1) == $1) ) {
i += 2
}
else {
rec = rec OFS $i
}
}
print rec
}
' file
awk-F'*\t*'-v OFS='\t''{
记录=1美元/2美元
对于(i=3;i请发布一些代码不起作用的记录我是否遗漏了什么?这应该不会有任何区别??FS是一个空格(或它设置为的任何内容)当这样使用时,使用制表符不会产生任何影响。是的,它不会产生任何影响。仍然不能处理实际数据。不能使用逗号,因为它出现在数据中。使用反勾号“。仍然不能处理我的数据。@IheOnwuka也许你可以尝试使用管道:
。另外,请确保没有任何尾随spaces。是的,我认为这样做可以奏效,但我真的想知道为什么更简单的解决方案不行。那么这是因为awk中有一个bug吗?@IheOnwuka再次检查,在第一个选项卡之前,您的示例中有空格,更新的答案应该是work@IheOnwuka数据中是否有与您的示例相同的^
,因为其中一个字段和选项卡之间有空格?是的$2在字段分隔符之前有空格。我被迫插入它以使联接工作,但我忘记了它在那里。请注意,如果给定一些输入值,它将删除错误的文本,例如,在前两个字段中的任意一个字段中重新设置元字符,或者如果任意一个字段中的文本恰好是p将恰好相邻的其他字段中的文本进行部分匹配(例如,如果$1=1234
和$2=mal
,并且在文本中的某个地方您有formal12345678
,则该字段将成为for5678
)。不幸的是,您真的需要使用字符串匹配,而不是regexp匹配,并包含边界字符,以便为此类问题提供健壮的解决方案。如果您发现需要,请告诉我们。谢谢。这非常及时,因为我遇到了重元字符中止。但我不需要如此健壮的东西,因此我已经放弃了th$2!~/[[]/{gsub($2 FS$1,“”)}当我在文件中遇到更多的元字符时,我会修复它。这种方法几乎总是以沮丧和绝望告终,所以我不会这么做。如果您的字段可能包含不需要的RE元字符,那么只需编写脚本以使用字符串而不是REs。如果生成的脚本比您认为必须的更健壮,那就不是了一件可怕的事情。我不希望脚本比保证的更复杂。直到160k条记录进入文件,我才遇到这个问题,所以我可能会遇到130万条记录中的10个实例。对我来说,这只是一个try-catch解决方法,因为该语言缺少错误处理。好的,请确保每次都读取每一行输出您可以运行它,因为有时当脚本行为不受欢迎时,它不会产生任何类型的错误或警告消息,而只是默默地破坏输出。元字符失败实际上是偶然的,因为有些(不是全部)其中一个突出了已经渗透进来的异常。我的计划是标记它们,以便可以查看它们,但这还不够好,因为机制太粗糙(它捕获不会失败的东西)。基本上,我需要尝试捕获错误处理,可能需要将此问题转移到提供此功能的语言中。
Input
1234 mal mal 1234 formal 12345678 blah
Output
1234 mal formal 12345678 blah
awk -F' *\t *' '{x=y;for(i=1;i<=NF;i++)(i>2&&$i==$2&&$(i+1)==$1&&i++)||x=x?x"\t"$i:$i;$0=x}1' file
awk -F' *\t *' -v OFS='\t' '{
rec = $1 OFS $2
for (i=3; i<=NF; i++) {
if ( ($i == $2) && ($(i+1) == $1) ) {
i += 2
}
else {
rec = rec OFS $i
}
}
print rec
}
' file