使用awk删除bash字符串中的重复项

使用awk删除bash字符串中的重复项,bash,awk,Bash,Awk,我试图应用这里提出的方法{}使用awk删除字符串中的重复项,但我注意到它没有按预期工作 例如,假设我们有: s="apple apple tree appleapple tree" 删除重复项我们希望得到以下输出: apple tree appleaplle 应通过对字符串应用以下命令(在链接中进行完整解释)来获取: 第一个apple副本已按要求擦除,但最后一个副本未被擦除。 事实上,如果我们打印每条记录的长度,我们会看到最后一条记录不是tree,而是tree+返回字符(我想是这样的) $a

我试图应用这里提出的方法{}使用awk删除字符串中的重复项,但我注意到它没有按预期工作

例如,假设我们有:

s="apple apple tree appleapple tree"
删除重复项我们希望得到以下输出:

apple tree appleaplle
应通过对字符串应用以下命令(在链接中进行完整解释)来获取:

第一个
apple
副本已按要求擦除,但最后一个副本未被擦除。 事实上,如果我们打印每条记录的长度,我们会看到最后一条记录不是
tree
,而是
tree
+返回字符(我想是这样的)


$awk'BEGIN{RS=”“;ORS=”“}{print length($0);print$0}'此示例显示您的怀疑是正确的:

$ echo "apple apple tree appleapple tree" | awk 'BEGIN{RS=" "; ORS=" "}
{ printf("%s |%s| ", length($0), $0)}'
5 |apple| 5 |apple| 4 |tree| 10 |appleapple| 5 |tree
|
我将使用FS获取所有不同的值,如下所示:

$ echo "apple apple tree appleapple tree" | awk '{for (i=1; i<=NF; i++) 
printf "%s %s\n", length($i), $i}'
5 apple
5 apple
4 tree
10 appleapple
4 tree

$echo“苹果树苹果树”| awk'{for(i=1;i如果不需要维护词序:

$ ( set -f; printf "%s\n" $s | sort -u | paste -sd" " )
apple appleapple tree
如果您确实想保留订单:

$ awk '                                                                                                      
    {          
        delete seen
        sep=""
        for (i=1; i<=NF; i++) {
            if (!seen[$i]++) {
                printf "%s%s", sep, $i
            }
            sep=OFS
        }
        print ""
    }
' <<<"$s"
apple tree appleapple
$awk'
{          
删除所见
sep=“”

对于(i=1;i,如前所述,通过将RS设置为
,这意味着
\n
不再是记录之间的字符,因此它成为输入行
“tree\n”
上最后一个字段的一部分

FWIW如果您有用于多字符的GNU awk,您可以执行以下操作:

awk -v RS='\\s+' '!seen[$0]++{printf "%s%s", (NR>1?OFS:""), $0} END{print ""}'

这是我为重复记录所做的:

awk '{if(arr[$1]!="true") print $1; arr[$1]="true"}' file.txt

使用
od-c scriptfile
查看您的文件是否有CR+LF行结尾,并使用
dos2unix
进行修复。这一次,它不是CR+LF问题,只是简单的引导错误。谢谢,是的,使用字段而不是记录似乎是实现这一点的更好方法。谢谢。我将选择第二个答案,因为我还不熟悉排序和过去。正如您和@MarcLambrichs在另一个答案中所建议的那样,使用字段似乎可以避免这个问题。然而,我仍然不明白使用记录会出现什么问题。您使用记录的方法的问题是,当您设置
RS=“”
这意味着行末尾的
\n
是最后一个字段的一部分,并且
树\n
不同。如果您在输入字符串的末尾添加一个空白字符并正确引用它(
是的,我现在明白了。事实上,我尝试在末尾添加一个额外的空格,但效果不错,但对“解决方案”不满意。问题现在很清楚了。在您的解释之后完全清楚了。没有什么神秘的东西了。使用该方法需要记录的多字符分隔符。
$ ( set -f; printf "%s\n" $s | sort -u | paste -sd" " )
apple appleapple tree
$ awk '                                                                                                      
    {          
        delete seen
        sep=""
        for (i=1; i<=NF; i++) {
            if (!seen[$i]++) {
                printf "%s%s", sep, $i
            }
            sep=OFS
        }
        print ""
    }
' <<<"$s"
apple tree appleapple
awk -v RS='\\s+' '!seen[$0]++{printf "%s%s", (NR>1?OFS:""), $0} END{print ""}'
awk '{if(arr[$1]!="true") print $1; arr[$1]="true"}' file.txt