Как подсчитать разделители и удалить перевод строки, если он не соответствует пороговому значению

У меня есть несколько файлов до миллиона записей, поступающих от поставщика.

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

Я думаю, что это вызвано символами, которые интерпретируются как перевод строки во время передачи в Linux, но я не уверен, поскольку мы никогда не видим исходные файлы Windows.

Мне нужна подпрограмма, которая будет подсчитывать количество разделителей в строке и, если оно ниже заданного порога, удалить перевод строки в конце записи. Так, например, мы знаем, что запись состоит из 29 столбцов и должна иметь 28 разделителей «конвейер» («|»). Когда мы получаем данные из-за ошибочного перевода строки, мы получаем две записи, например, с 10 полями и 9 разделителями. и второй с 19 полями и 18 разделителями. Вот пример данных, измененных в целях безопасности:

9999999999|Duck Donald|87|||999999999|9999999999|XX999999|||Z99999|999 Planet Ln|||Trumpet
ville|ZZ|99999||||||ZZ|P|9999999999|F|||

Обратите внимание, что строка разделяется на слове Trumpetville. Это связано с тем, что был вставлен или неправильно переведен символ перевода строки. Снова ищем программу для подсчета разделителей и удаления перевода строки, если количество разделителей упадет ниже указанного порогового значения.

0
10.01.2017, 17:04
3 ответа

Try:

sed -e :1 -e 's/|/|/28;t' -e 'N;s/\n//;t1' < your-file

Or:

awk -F'|' '{while (NF < 29 && (getline nextline) > 0)
   $0 = $0 nextline; print}' < your-file

В случае, если текст имеет разделители строк CRLF Microsoft, вы можете сначала обработать файлы с помощью dos2unix.

1
28.01.2020, 02:46

bash script

Я прочитал, что оригинальный ответ на самом деле не то, что вы ищете. Пожалуйста, ознакомьтесь со следующим сценарием. Это работает только тогда, когда вы заранее знаете количество элементов входного файла:

#!/bin/bash

infile=/home/wokie/duck.txt
outfile=/home/wokie/duck2.txt
# Define the amount of elements/columns in a row
maxelem=28

# Read the file, strip all newline characters and create one big variable
inputOneline=$(cat $infile | dos2unix | tr -d '\n')

count=0
# Read through the variable and split elements
for element in ${inputOneline//|/ }
  do
  if [ $count -lt $maxelem ]
    then
      # Write element to outfile while suppresing newline (-n) 
      echo -n "$element|" >> $outfile
      count=$[$count +1]
    else
      # Write newline to outfile when maximum elements is reached
      echo >> $outfile
      count=0
  fi
done

Вся идея состоит в том, чтобы сначала удалить все новые строки, после этого новый файл будет собран вместе с новыми строками в нужных местах.

dos2unix

Скрипт использует отличный инструмент под названием dos2unix. Запустив dos2unix только с именем файла в качестве параметра, он автоматически преобразует входной файл (Windows) в формат unix.

Если запустить инструмент с параметром -id, подсчитывается количество случаев CRLF, например:

[test@testsystem ~]$ dos2unix -id /home/wokie/test2.txt 5 /home/wokie/test2.txt

В файле примера 5 случаев.

Вы можете найти инструмент dos2unix здесь: https://sourceforge.net/projects/dos2unix/. Большинство дистрибутивов предоставляют dos2unix в стандартной комплектации или предоставляют возможность установки с помощью apt-get или dnf.

0
28.01.2020, 02:46

Предполагая, что нежелательный CRLF в данных не встречается в начале поля, вы можете:

Заменить предполагаемый CRLF в конец строки с Linux EOL, LF .

Это должно происходить после вертикальной черты. Эфир напрямую или через пробел. Поэтому замените строки «pipe space CRLF» и «pipe CRLF» на «pipe space LF» или «pipe LF»

0x7C 0x20 0x0D 0x0A и 0x7C 0x0D 0x0A

на

0x7C 0x20 0x0A и 0x7C 0x0A

Теперь единственный CRLF , который остался, находится в данных. Замените эту строку «CRLF» пробелом или нулем.

0x0D 0x0A до 0x20

править:

Предполагаемый EOL должен быть между 2 трубами.

| данные | CRLF

| данные |

0x7C 0x0D 0x0A 0x7C
0
28.01.2020, 02:46

Теги

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