#shell
Вопрос:
У меня есть несколько файлов фиксированной длины, в которых каждая позиция или диапазон позиций зарезервированы для определенного поля. Первые несколько полей-это год, срок, имя, должность, пол…
Год начинается с позиции 1 и имеет длину 2
Срок начинается с позиции 3 и имеет длину 1
Имя начинается с позиции 4 и имеет длину 35
DOB начинается в позиции 39 и имеет длину 6
Пол начинается с позиции 45 и имеет длину 1 …
Это справедливо для всех файлов. Не все поля присутствуют всегда. Например, поле Имя может содержать 35 пробелов/пробелов, так как об этом не сообщалось. То же самое может быть верно и в отношении других областей.
Мне нужно выполнить поиск в поле имени (независимо от того, имеет ли оно значение или нет, и заменить его содержимое фиктивной строкой, которая может быть «xxxxxxxx», но длина не должна превышать 35, и после замены строки положение всех полей не должно было измениться. Все файлы содержат 80 полей.
Пример файла, содержащего 3 строки. Каждая строка начинается с 182:
182 1 405080711 001 0425594
07 5 4170000000000000 00000000000000000000000000000000000000000000 0000
9 05000002
182 1 205080712 001 0480201
07 5 3300000000000000 00000000000000000000000000000000000000000000 0000
05000004
182 2 005080713 001 0425824
07 5 3080000000000000 00000000000000000000000000000000000000000000 0000
05000005
«‘ Я использую следующую команду sed для замены пустого поля имени строкой ниже. Однако это перезаписывает все поля перед именем, которое начинается с позиции 35
сед -И/^(.{3})(.{36})/Имя студента-Фамилия/’ Имя файла «‘
Откройте для использования любую другую команду, такую как awk и т. Д. Фактические пробелы между полями могут здесь не отображаться из-за автоматического форматирования. В приведенной выше примерной строке 1 на самом деле 41 пробел между «182» и «1». Введите описание изображения здесь, буду признателен за любую помощь.
Ответ №1:
С помощью perl
:
perl -pe 'BEGIN { $name = sprintf "% -35.35s", "xxxxxxxx" }
substr($_, 3, 35) = $name' input.txt
perl
использует индексы на основе 0, поэтому это заменяет 35 символов каждой строки входного файла, начиная с 4-го символа, значением xxxxxxxx
, заполненным достаточным количеством пробелов в конце, чтобы всего получилось 35 символов (и если xxxxxxxx
длина более 35 символов, усекает ее до 35). Затем измененная строка выводится на стандартный вывод. Используйте perl -i -pe '...' input.txt
для изменения файла на месте.
Или аналогичная awk
версия:
awk 'BEGIN { name = sprintf "% -35.35s", "xxxxxxxx" }
{ printf "%s%s%sn", substr($0, 1, 3), name, substr($0, 39) }' input.txt
awk
У s substr
нет способа заменить часть строки, как perl
у s, поэтому он извлекает части до и после поля имени и распечатывает их все с новым значением имени. Не так элегантно, но выполняет свою работу.
Комментарии:
1. Я попробовал версию Perl, и она отлично сработала! Большое спасибо. Очень признателен.