使用单行

时间:2016-07-07 15:09:08

标签: bash shell csv awk sed

我想在字符串变量中添加一个新项目,该变量表示以逗号分隔的列表,同时防止项目两次。

我想出了这个python解决方案:

python -c "import sys ; first = set(sys.argv[1].split(',')) ; all = first.union(set(sys.argv[2:])) ; print ','.join(all)" 1,2 4 3 2
1,3,2,4

多行:

import sys
first = set(sys.argv[1].split(','))
all = first.union(set(sys.argv[2:]))
print ','.join(all)

虽然该解决方案有效,但它不太适合shell脚本中的单线程。

我使用awksed或普通bash尝试了一些事情,但没有任何事情会导致短暂但仍然稳定的解决方案。有没有人知道如何使用简短的命令行习惯用语来表达它?

7 个答案:

答案 0 :(得分:3)

awk救援!

$ echo -n "1,2 4 3 2" | awk -v RS='[, ]' '!a[$0]++' | paste -sd,

1,2,4,3

答案 1 :(得分:1)

Perl解决方案:

perl -le 'undef @h{ (split /,/, shift), @ARGV }; $, = ","; print keys %h' 1,2 4 3 2

答案 2 :(得分:1)

它不是单行,但仍然是一个干净的shell解决方案:

observe

如果你想要一个衬里,可以把它放到一个函数中:

#!/bin/bash
list="1,2"
new_items="4 5 3"

for i in $new_items ; do
    # The `\b` does match at word boundaries
    ! grep -Eq "\b$i\b" <<< "$list" && list="$list,$i"
done
echo "$list"

称之为:

function add_items() {
    list="$1"
    new_items="$2"
    for i in $new_items ; do
        ! grep -Eq "\b$i\b" <<< "$list" && list="$list,$i"
    done
    echo "$list"
}

答案 3 :(得分:1)

bash选项:将您的项目列表保存在带有前导和尾随逗号的字符串变量(list下方)中。这样每个项目都以逗号开头和结尾,这使事情变得更容易。要添加项目:

new_item=42   # or whatever
list="${list//,${new_item},/,}${new_item},"

${list//...}删除所有重复项(//表示全局替换),然后${new_item},将新项目粘贴到列表末尾。要添加多个项目:

list=",1,2,"
for x in 4 3 2 ; do list="${list//,$x,/,}$x," ; done

要从列表中删除逗号,您可以使用

list="${list#,}"
list="${list%,}"

上面您的具体示例的单行,但扩展了更多的测试用例,将是:

bash -c 'list=",$1,"; shift; for f in "$@"; do list="${list//,$f,/,}$f,"; done; list="${list#,}"; list="${list%,}"; echo $list' -- 1,2 3 4 44 444 1 2

但请注意,该行的大部分内容只是从参数中获取列表,然后输出到stdout。在脚本中,list="${list//,$x,/,}$x,"就是您所需要的。

答案 4 :(得分:0)

使用sed

echo 1,2 3 2 4 | sed -r ':a {s/([^, ]+)(.*)\1/\2,\1/;ta}; s/ /,/g; s/,+/,/g; s/^,//'

答案 5 :(得分:0)

更多AWK:

$ cat test.in
1,2 3 2 4
5,4 3 4 5

$ cat test.in|awk 'BEGIN {FS="[ ,]";OFS=","} {delete a; delete b; n=split($0,a,FS); for(i in a) b[a[i]]=n--; for(i in b) printf "%s%s",i,(b[i]>1)?OFS:ORS}'
1,2,3,4
3,4,5

答案 6 :(得分:0)

AWK越来越多:

$ echo 1,2 3 2 4|awk 'BEGIN {RS="[ ,\n]";OFS=","} {a[$0]=++i} END {for (j in a) printf "%s%s", j, a[j]<NR?OFS:ORS}'
1,2,3,4