web-dev-qa-db-ja.com

ファイルに行を追加して、ファイルの長さが等しくなるようにします

N列で行(行)の数が異なる.csvファイルがたくさんあります。空の行をできるだけ多く追加したい;...;(Nセミコロン)同じ長さにします。最長のファイルの長さを手動で取得できますが、これを自動的に実行することもできます。

例えば:

私が持っています、

file1.csv

128; pep; 93; 22:22:10; 3; 11
127; qep; 93; 12:52:10; 3; 15
171; pep; 73; 22:26:10; 3; 72

file2.csv

128; pep; 93; 22:22:10; 3; 11
127; qep; 93; 12:52:10; 3; 15
121; fng; 96; 09:42:10; 3; 52
141; gep; 53; 21:22:10; 3; 62
171; pep; 73; 22:26:10; 3; 72
221; ahp; 93; 23:52:10; 3; 892

file3.csv

121; fng; 96; 09:42:10; 3; 52
171; pep; 73; 22:26:10; 3; 72
221; ahp; 93; 23:52:10; 3; 892
141; gep; 53; 21:22:10; 3; 62

私は欲しい、

file1.csv

128; pep; 93; 22:22:10; 3; 11
127; qep; 93; 12:52:10; 3; 15
171; pep; 73; 22:26:10; 3; 72
;;;;;
;;;;;
;;;;;

file2.csv

128; pep; 93; 22:22:10; 3; 11
127; qep; 93; 12:52:10; 3; 15
121; fng; 96; 09:42:10; 3; 52
141; gep; 53; 21:22:10; 3; 62
171; pep; 73; 22:26:10; 3; 72
221; ahp; 93; 23:52:10; 3; 892

file3.csv

121; fng; 96; 09:42:10; 3; 52
171; pep; 73; 22:26:10; 3; 72
221; ahp; 93; 23:52:10; 3; 892
141; gep; 53; 21:22:10; 3; 62
;;;;;
;;;;;
5
myradio

コメントの提案をありがとう@Sparhawk、私​​はそれらに基づいて更新します、

#!/bin/bash

emptyLine=;;;;;;;
rr=($(wc -l files*pattern.txt |  awk '{print $1}' | sed '$ d'))
max=$(echo "${rr[*]}" | sort -nr | head -n1)
for name in files*pattern.txt;do
    lineNumber=$(wc -l < $name)
    let missing=max-lineNumber
    for((i=0;i<$missing;i++));do
        echo $emptyLine >> $name
    done
done

まあ、エレガントでも効率的でもありません。実際には、データのサイズが小さいことを考えると、永遠に聞こえる数秒かかります。それにもかかわらず、それは機能します、

#!/bin/bash

emptyLine=;;;;;;;
rr=($(wc -l files*pattern.txt |  awk '{print $1}' | sed '$ d'))
max=$(echo "${rr[*]}" | sort -nr | head -n1)
for name in $(ls files*pattern.txt);do
    lineNumber=$(cat $name | wc -l )
    let missing=max-lineNumber
    for((i=0;i<$missing;i++));do
        echo $emptyLine >> $name
    done
done

files*pattern.txtでファイルを一覧表示するために使用できるパターンがある場合は、このファイルをファイルがあるディレクトリにまとめます。

3
myradio

@myradioの回答の改善。
awkで記述されたループ内の部分。これははるかに高速であるはずです。

_max=$(wc -l file*.csv | sed '$ d' | sort -n | tail -n1 | awk '{print $1}' )
for f in file*.csv; do
    awk -F';' -v max=$max \
      'END{
         s=sprintf("%*s",FS,"");
         gsub(/ /,"-",s);
         for(i=NR;i<max;i++)
           print s;
       }' "$f" >> "$f"
done
_

_-F_を使用して、ファイルの正しいフィールド区切り文字を設定します(ここでは_-F';'_)。

s=sprintf();gsub();部分は、FS(=フィールド区切り文字)の適切な量を動的に設定します( via )。
必要に応じて、それを_print ";;;;;"_またはその他の静的コンテンツに置き換えることができます。

2
pLumo

各ファイルの行を1回だけカウントするには、次のようにします。

wc -l *csv |sort -nr| sed 1d | {
    read max file
    pad=$(sed q "$file"|tr -cd ";")  # extract separators from first record
    while read lines file ; do
        while [ $((lines+=1)) -le $max ] ; do
                echo "$pad" >> "$file"
        done
    done
}

ファイル名に改行があると、sortループとwhile readループの両方で問題が発生しますが、通常のスペースを含むファイル名は処理できます。

1
JigglyNaga