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_Csv_Awk_Sed - Fatal编程技术网

Bash 将项目添加到带有一行的逗号分隔列表中

Bash 将项目添加到带有一行的逗号分隔列表中,bash,shell,csv,awk,sed,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 perl -le 'undef @h{ (split /,/, shift), @ARGV };

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

我提出了这个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
perl -le 'undef @h{ (split /,/, shift), @ARGV }; $, = ","; print keys %h' 1,2 4 3 2
#!/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"
多行:

import sys
first = set(sys.argv[1].split(','))
all = first.union(set(sys.argv[2:]))
print ','.join(all)
虽然解决方案可行,但它并不非常适合shell脚本中的一行程序

我用
awk
sed
或plain
bash
尝试了一些方法,但都没有找到一个简短但仍然稳定的解决方案。有人知道如何用一个简短的命令行习惯用法来表达这一点吗?

Perl解决方案:

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
perl -le 'undef @h{ (split /,/, shift), @ARGV }; $, = ","; print keys %h' 1,2 4 3 2
#!/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"

使用
sed

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

awk
救援

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

1,2,4,3

这不是一个单一的班轮,但imo仍然是一个干净的壳牌解决方案:

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
perl -le 'undef @h{ (split /,/, shift), @ARGV }; $, = ","; print keys %h' 1,2 4 3 2
#!/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"

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,”
是您所需要的一切。

更多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
越来越多的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

$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]
echo 5,4,4 5 | sed…
输出
,3,4,5
@JamesBrown感谢您的提示。这取决于
b
的索引顺序对应于
a
w.r.t.的索引顺序。打印
of s
RS
,但情况并非总是如此。例如,当我用调用您的程序时de>echo'5,4,3,2,1,5 6'|啊…
我得到了
2,3,4,56,1,
。嗯,我没有,我得到了
1,2,3,4,5,6
。我目瞪口呆。你在说什么(不是双关语)?:-)使用本机bsd awk的Mac OS X。使用gawk,我与前面的示例没有问题,但它确实使用
$echo'5,4,3 9 8'| gawk…
。这给了我
3,4,5,89,