将文件中的唯一列提取到以特定顺序排列的逗号分隔列表

时间:2018-10-24 17:03:17

标签: bash awk

我有一个包含这些值的.csv文件

product,0 0,no way
brand,0 0 0,detergent
product,0 0 1,sugar
negative,0 0 1, sight
positive, 0 0 1, salt

,我想用逗号分隔的行按排序顺序创建文件,但“负”始终在末尾。 所以我要    [“品牌”,“正面”,“产品”,“负面”]

我无法自动执行此过程,所以我做了

  1. awk -F ',' '{print $1}' file.csv | sort | uniq -c > file2.txt

  2. awk '{if(NR>1) printf ", ";printf("\"%s\"",$0)} END {print ""}' file2.txt > file3.txt 我得到“品牌”,“负面”,“正面”,“产品”

  3. 然后我将“负号”手动移到末尾,并将[和]附加到前面和后面以得到

    ["brand","positive","product","negative"]
    

有没有办法使它更有效并使流程自动化?

5 个答案:

答案 0 :(得分:0)

这对我有用:

cut -d, -f1 file.csv | sort -u | sed "/^negative/d" | tr '\n' ',' | sed -e 's/^/["/' -e 's/,/","/g' -e 's/$/negative"]/'

答案 1 :(得分:0)

这里有一个gnu awk命令可以使它工作:

awk -F, '{
   a[$1] = ($1 == "negative" ? "~" : "") $1
}
END {
   n = asort(a)
   printf "["
   for (i = 1; i <= n; i++) {
      sub(/^~/, "", a[i])
      printf "\"%s\"%s", a[i], (i < n ? ", " : "]\n")
   }
}' file.csv

["brand", "positive", "product", "negative"]

答案 2 :(得分:0)

有很多方法可以解决这个问题。您是否真的希望结果看起来像一个JSON数组,并在列名前后加上方括号和引号?如果是这样,那么jq可能是一个很好的生成工具。这样的事情将作为一个单独的jq程序来完成:

jq -csR '[split("\n")|
          map(select(length>0))[]|
          split(",")[0]]|
          sort_by(if .=="negative" then "zzzz" else . end)' file.csv

哪个输出:

["brand","positive","product","negative"]

如果只希望标题用逗号分隔,而没有其他标点,则适合于CSV文件的标题,则可以使用更多传统的文本操作命令:

cut -d, -f1 file.csv | 
  sed 's/negative/zzz&/' | 
  sort -u | 
  sed 's/zzz//' |
  paste -d, -s - 

或者您可以通过在末尾添加jq标志和另一个管道来稍微修改-r命令:

jq -csrR '[split("\n")|
           map(select(length>0))[]|
           split(",")[0]]|
           sort_by(if .=="negative" then "zzzz" else . end)|
           join(",")' file.csv

哪个输出:

brand,positive,product,negative

答案 3 :(得分:0)

另一种易于理解的解决方案

$ awk -F, '{print ($1=="negative"?1:0) "\t\"" $1 "\""}' file | # mark negatives
  sort | cut -f2 | uniq |                                      # sort, cut, uniq
  paste -sd, | sed 's/^/[/;s/$/]/'                             # serialize, add brackets


["brand","positive","product","negative"]

答案 4 :(得分:0)

使用Perl单线版

$ cat unique.txt
product,0 0,no way
brand,0 0 0,detergent
product,0 0 1,sugar
negative,0 0 1, sight
positive, 0 0 1, salt

$ perl -F, -lane ' { $x=$F[0];$x=~s/^(negative)/z\1/g;$rating{$x}++ } END {$q="\x22";$y=join("$q,$q",sort keys %rating) ; $y=~s/${q}z/$q/g; print "[$q$y$q]" }' unique.txt
["brand","positive","product","negative"]

$