【问题标题】:Bash sort CSV large file and output sorted to separate filesBash 对 CSV 大文件进行排序并将输出排序到单独的文件
【发布时间】:2017-08-01 23:27:29
【问题描述】:

我有大 (4GB) 分号分隔文件 (1.txt):

 - "3321";"<a href='/files/goods/edit/647/'><u>[ID 647]</u></a> Шорты";"2015-09-06 18:39:17";"1590";"1";"500";"";"Лейла";"878785";"Да";"80.140.1.38"
 - "2780";"<a href='/files/goods/edit/647/'><u>[ID 647]</u></a> Шорты";"2015-09-06 18:42:51";"1590";"1";"500";"";"Мара";"8664456";"Да";"46.00.00.2"
 - "3352";"<a href='/files/goods/edit/698/'><u>[ID 698]</u></a> Deck";"2015-09-06 19:05:42";"990";"1";"400";"";"Ed";"456452";"Нет";"80.26.00.00"
 - "3764";"<a href='/files/goods/edit/669/'><u>[ID 669]</u></a> Fish";"2015-09-06 18:36:18";"1390";"1";"530";"";"Ann";"545566";"Нет";"80.00.35.90"
 - "3323";"<a href='/files/goods/edit/669/'><u>[ID 669]</u></a> Fish";"2015-09-06 18:54:18";"1390";"1";"530";"";"юрий";"99393";"Да";"85.141.00.100"
 - "32763";"<a href='/files/goods/edit/430/'><u>[ID 430]</u></a> Radio";"2015-09-06

我需要按第二列对1.txt 进行排序,并根据第二列名称将所有结果输出到单独的文件中。

我这样做:

sed -r -i -e 's#"<a href=\x27\/files\/goods\/edit\/##g' 1.txt | sed -r -i -e 's#\/\x27>#;#g' 1.txt | sort --field-separator=';' --key=2 1.txt

但是现在如何拆分 1.txt 文件并将所有相同的 ID(第二列)值行放在单独的文件中并计算文件中的记录?拥有647_count.txt698_count.txt669_count.txt430_count.txt 之类的东西。

【问题讨论】:

  • 似乎文件名 647_count.txt 包含第二列的最后一部分 "&lt;a href='/files/goods/edit/647/'&gt;" 但不是 count records in file
  • 647_count.txt 不包含任何内容,因为我不知道该怎么做
  • 我指的是文件名,而不是内容。文件名是否应该包含ID 值?
  • 应该包含ID和记录数

标签: linux bash sorting unix awk


【解决方案1】:

重击:

err() { echo "$@" >&2; return 1; }

#the line sorting
re='^[^;]*;[^;]*ID ([0-9][0-9]*)'
n=0
while read -r line
do
    let n++
    if [[ "$line" =~ $re ]]
    then
        echo "$line" >> "${BASH_REMATCH[1]}_COUNT.csv"
    else
        err "$n-th line [$line] doesn't match"
    fi

done

#rename the ID_COUNT.csv to the real value of lines
shopt -s nullglob
for file in [0-9][0-9]*_COUNT.csv
do
    mv -n "$file" "${file//_COUNT/_$(grep -c '^' "$file")}"
done

【讨论】:

    【解决方案2】:

    试试下面的awk 脚本(我们称之为parser.awk):

    BEGIN { FS=";"; }   # field separator
    { 
        if (match($2, /[0-9]+/)) {           # matching `ID` value
            m=substr($2, RSTART, RLENGTH);
            a[m]++;                          # accumulating number of lines for each `ID`
            print > m"_count.txt";    # writing lines pertaining to certain `ID` into respective file
        } 
    }
    END {
        for(i in a) { 
            print "mv "i"_count.txt "i"_"a[i]".txt"  # renaming files with actual counts
        }
    } 
    

    用法:

    awk -f parser.awk 1.csv | sh
    

    对于您在问题中发布的输入片段,我已获得以下文件列表:

    430_1.txt 
    647_2.txt 
    669_2.txt
    698_1.txt 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-09
      • 1970-01-01
      • 2017-09-30
      • 2017-06-23
      • 1970-01-01
      • 1970-01-01
      • 2011-04-03
      • 2013-05-15
      相关资源
      最近更新 更多