Как я могу получить все это значение 7I45432ZX
из следующих строк:
PW*3434*453*256*PE*UB
PO*00*NE*7I4543
2ZX**20140617
PW*3434*453*256*PE*UB
PO*00*NE*7I4543
2ZX**20140617
Это код, который я пробовал:
grep -oP 'PO.00.[A-Z][A-Z].\K[A-Z0-9_-]*' < file.txt
У меня есть этот код выше, однако, сгенерированный вывод - это только этот 7I4543
, а не весь 7I45432ZX
, что, как предполагается, является моим ожидаемым результатом. Есть ли что-то, что я должен был изменить или добавить после .\K
, чтобы получить все значение?
Попробуйте это:
awk -F "*" '{ if ($1 == "PO") { lastTok = $(NF); getline; print lastTok "" $1;}}' input.txt
awk используют "*" в качестве разделителя и печати последнее поле строки, которые запускаются с ПО, сопровождаемой первым полем следующей строки.
вывод:
7I45432ZX
7I45432ZX
, Если у Вас есть файл в формате DOS, необходимо использовать команда dos2unix.
Попробуйте следующую остроту:
$ cat file.txt | perl -e 's/\s//g && print "$_\n" for join("", <>) =~ /\*([\w\s]+)\*\*/g'
7I45432ZX
7I45432ZX
Я в основном ищу шаблон между звездой *
и 2 звезды **
. После того, как найденный, я просто удаляю пробелы/возвраты каретки перед печатью.
Если Вы не хотите устанавливать Perl
или что-либо еще и хочет пойти со старым добрым стандартом coomand инструменты строки, можно использовать что-то вроде:
sed '1 d
2 s/^PO\*00\*[A-Z][A-Z]\*\([A-Z0-9_-]*\)$/\1/
3 s/^\([A-Z0-9_-]*\)\*\*.*$/\1/' < file.txt
Это принимает это
2
3
и 3
5
и добавьте 2 d
и 4 d
команды на дополнительных строках собой;tr
как так: | tr -d "\n\r"
[Править]
sed
часть также предполагает, что Вы имеете UN*X
текстовые строки. Кроме того, кажется, существует спор, насколько строгий шаблоны должны быть. Я чувствую, что OP предложил определенную степень строгости. Так или иначе, sed
шаблоны могут быть легко скорректированы для принятия DOS
окончания строки, например, путем окончания в \r*$
. До grep
и sed
:
grep -oPz '7I4543$\n^2ZX' file |sed '$!N;s/\n//'
7I45432ZX
7I45432ZX
grep
шаблоны 7I4543
и 2ZX
и все между ними в нескольких строках. $
в точках команды grep к концу строки и ^
точки запускаются строки.
sed
соединяет каждую пару строк к одному линейному. $
точки текущая строка, N
точки к следующей строке. тогда замените/удалите новую строку \n
между этим строки.
-o, --only-matching
Print only the matched (non-empty) parts of a matching line,
with each such part on a separate output line.
-P, --perl-regexp
Interpret PATTERN as a Perl compatible regular expression (PCRE)
-z, --null-data
Treat the input as a set of lines, each terminated by a zero byte (the ASCII
NUL character) instead of a newline. Like the -Z or --null option, this option
can be used with commands like sort -z to process arbitrary file names.
Возможный другой grep
с:
$ grep -oPz '7I4543$(^2ZX|\n)+'
$ grep -oPz '7I4543$\s^2ZX'
Через GNU awk,
$ awk -v RS="PO" '/^\*/{gsub(/^.*\*/,"",$1); gsub(/\*.*$/,"",$2); print $1$2}' file
7I45432ZX
7I45432ZX
Установка pcregrep:
sudo apt-get install pcregrep
и затем выполненный:
pcregrep -oM "PO.00.[A-Z][A-Z].\K[A-Z0-9_-].*\s+.*\*" < file.txt | tr -d '\n' | sed -e 's/\*\*/\n/g'
Вывод:
7I45432ZX
7I45432ZX
Вот объяснение того, что делает сценарий. В первую очередь, я должен был сделать Ваше исходное чтение сценария через переводы строки, и затем после этого оно произведет результат на двух отдельных строках, если я не заставил его записать через переводы строки также. Последняя часть сценария sed -e 's/\*\*/\n/g'
помещает перевод строки после каждого разделителя согласно просьбе автором вопроса в комментарии к этому ответу.