Переместить каждые 500 файлов в новый каталог

Достаточно просто определить, какие строки ввода имеют более 21 поля. например.

awk -F, 'NF>21' input.txt

Исправить это не так-то просто. Вам придется вручную редактировать эти строки (, например. с помощью viили nanoили предпочитаемого вами редактора ), потому что у скрипта нет простого способа узнать, КАКИЕ поля являются поддельными (или, наоборот, какие поля содержат запятые, которых не должно быть ).

Это работа, требующая настоящего интеллекта, а не простого (или даже сложного )поиска -и -замены эвристики. Это также требует фактического знания вашего набора данных.

Вот почему настоящие CSV файлы содержат строковые поля в кавычках, и поэтому настоящие синтаксические анализаторы CSV понимают строковые поля в кавычках.

Если вы можете получить файл, разделенный запятыми -, для создания реального CSV-файла со строковыми полями в кавычках, тогда обработка будет намного проще. Это реальное решение этой проблемы -устранить проблему в источнике.


Другие ответы отметили, что по крайней мере часть того, что вам нужно сделать, это объединить любое поле, начинающееся с пробела, с предыдущим полем.

Если вы собираетесь это сделать, вам также следует преобразовать ввод в правильно отформатированный CSV. Например:

$ perl -e '
use Text::CSV qw(csv);
$csv = Text::CSV->new();

while($row = $csv->getline(ARGV)) {

  # merge fields beginning with whitespace with the previous field.
  for ($i=1; $i <= @$row; $i++) {
    if ($row->[$i] =~ m/^\s/) {
      $row->[$i-1].= ",". $row->[$i];
      $row->[$i] = undef;
    };
  };

  # delete any undef-ed fields    
  @$row = grep{defined $_} @$row;

  $csv->say(STDOUT, $row);
};
' input.txt

Примечание:

  • Команда $csv->getline()получает полную строку данных CSV, независимо от того, находятся ли они все в одной строке или распределены по нескольким строкам, например, из-за многострочных -строк в кавычках.

    Это не имеет особого отношения к вашему текущему входному файлу (, потому что это не CSV, он просто немного похож на CSV-файл ), но очень полезен при работе с реальными CSV-файлами.

Пример вывода:

BusinessDate,SourceSystemId,IceIndexId,IceIndexName,ComponentId,ComponentReferenceType,ComponentType,ComponentName,ComponentIssuerCIS,ComponentIssuerName,ComponentWeighting,IceCurveID,IceCurveName,RiskyCurveCIS,OriginalWeighting,DerivedWeighting,indexType,cafName,indexStartDate,indexCurrency,componentCurrency
2019-09-19,ICEEUR,11260370,risky_CMBX3_AM_19HGEMAC7.usd,20173QAG6,CUSIP,BOND,"GCCFC 2007-GG9 A-M",FCMT7US,"COML MORT TST 2007-GG9",0.04,19063270,risky_20173QAG6_FCMT7US.usd,FCMT7US,0.04,0.04,indexCds,index_risky_CMBX3_AM_19HGEMAC7.usd,2010-02-09,USD,USD
2019-09-19,ICEEUR,11260370,risky_CMBX3_AM_19HGEMAC7.usd,61753JAF6,CUSIP,BOND,"MSC 2007-IQ13 AM",Z01IYUS,"MORGAN STNLY CAP I TST 2007-IQ13",0.04,19059680,risky_61753JAF6_Z01IYUS.usd,Z01IYUS,0.04,0.04,indexCds,index_risky_CMBX3_AM_19HGEMAC7.usd,2010-02-09,USD,USD
2019-09-19,ICEEUR,12345400,risky_itraxx_europe32_14.eur,XSNOREFOB258,ISIN,BOND,NOREFOB_BANCO_SANTANDER_SA,BBDERES,"BANCO SANTANDER SA, MADRID HO",0.008,20286090,risky_bank_bsch_14.eur,BBDERES,0.008,0.008,indexCds,index_risky_itraxx_europe32_14.eur,2019-09-18,EUR,EUR

Это объединило два проблемных поля на 4-й строке как"BANCO SANTANDER SA, MADRID HO"

Обратите внимание, что ВСЕ поля со встроенными пробелами (и любыми другими потенциально проблемными символами )также заключаются в двойные -кавычки. то есть вывод теперь правильно отформатирован CSV.

Это устраняет только одну известную нам проблему. Могут быть и другие, о которых мы (, то есть вы ), еще не знаем. например. могут быть дополнительные запятые, за которыми сразу не следует пробел.

Этот сценарий (, как и другие ответы здесь, которые реализуют вариант этого алгоритма ), будет разбивать любые входные строки, где поле должно начинаться с символа пробела (s ). В вашем образце входных данных их нет, но небезопасно предполагать это из размера выборки из одного заголовка и трех строк данных.

Настоящее решение по-прежнему заключается в том, чтобы исправить проблему в источнике , заставив его выводить правильно отформатированный CSV вместо этого испорченного мусора.


Если вы не можете заставить программу, производящую эти выходные данные, правильно цитировать CSV, другой альтернативой является использование разделителя столбцов, которого нет в данных . Символ вертикальной черты |или точка с запятой -двоеточие ;или символ табуляции (0x09, Ctrl-I,\t)часто являются хорошим выбором для разделителей.

-2
27.11.2020, 18:27
1 ответ

В системе на базе Linux -или другой системе, использующей GNU find, вы можете использовать цикл примерно так

find -maxdepth 1 -type f -printf '%s\t%P\0' |
    sort -z -rn |
    (
        # x is max files per directory; d is directory number; k is file counter
        x=500 d=1 k=1
        while IFS=$'\t' read -r -d '' size path
        do
            printf "%d\t%d\t%s\n" $k $d "$path"    # File nr, Directory nr, Filename
            echo "##" mkdir -p "/path/to/dir-$d"
            echo "##" mv -f "$path" "/path/to/dir-$d/${path##*/}"

            [[ $((k++)) -ge $x ]] && { k=1; ((d++)); }    # Next directory
        done
    )

Удалите echo '##'из двух строк действия в цикле, когда вы уверены, что они будут делать то, что вы от них хотите. Закомментируйте printf, если вам не нужен отчет о том, что и куда идет.

2
18.03.2021, 22:46

Теги

Похожие вопросы