1

Мы анализируем некоторые большие файлы EDI, которые не содержат CR/LF. Тем не менее, они имеют ~ (тильда) в качестве разделителя сегмента.

Я пытаюсь извлечь контрольную запись для файла, и последние байты моего файла размером 120 МБ выглядят примерно так:

~REF*1L*0711882~SE*62300*39093~GE*1*500001242~IEA*1*500001241~

В файле есть только одна контрольная запись, и она всегда начинается с ~SE .

Итак, есть ли простой способ, используя стандартные инструменты Unix cut, awk, grep и т.д., Чтобы вырезать этот файл для получения сегмента SE * 62300 * 39093, кроме преобразования ~ в CRLF и выведения последних трех строк файла?

Отказ от ответственности:
Я не гуру Unix, поэтому ответ может быть очевидным для опытного пользователя. Кроме того, я не контролирую формат файла.

3 ответа3

4

Хотя я вижу, что не хочу изменять исходный файл, вы можете сделать перевод в трубе. Таким образом, вы не изменяете данные, но вы все равно получаете преимущество (в терминах утилит Unix) от превращения ~ в конец строки.

Это должно сделать трюк:

cat ding | tr "~" "\n" | tail -3

Это не самая эффективная вещь во вселенной, но даже для файла размером 120 МБ запускать не стоит.

Обратите внимание, что кавычки на двух наборах не являются обязательными - и ~ и \n будут интерпретироваться оболочкой, если вы отбросите кавычки.

3

Вы можете сделать это с:
tr "~" "\n" < edi_file | tail -20 | grep ^SE

Tr tr переводит все тильды на новые строки. (Они представлены \n).

Выходные данные затем подаются в tail, который отбрасывает все, кроме последних 20 строк.

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

Я не выбрал этот вариант, потому что ваш пост помечен как универсальный Unix, а не как современный Linux с современными инструментами GNU и специфическими расширениями GNU.

Наконец, grep фильтрует последние строки в те, которые содержат SE, а символ carret (^) проверяет, что он находится в начале строки. (Предотвращение таких вещей, как ~ foooo SE foobarquz ~ SE wewantthispartonly ~ boobar ~ для показа двух строк).

2

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

Используйте tac чтобы прочитать файл в обратном порядке, затем возьмите 20 первых строк (обратного, то есть самого последнего), снова поверните в обратном порядке, чтобы получить исходный порядок, теперь grep:

tac -s~ edi_file | head -n 20 | tac | grep ^SE

Помните, что вы не можете seek() трубу!

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .