Comment obtenir cette valeur entière _7I45432ZX
_ à partir des lignes ci-dessous:
_PW*3434*453*256*PE*UB
PO*00*NE*7I4543
2ZX**20140617
PW*3434*453*256*PE*UB
PO*00*NE*7I4543
2ZX**20140617
_
C'est le code que j'ai essayé:
_grep -oP 'PO.00.[A-Z][A-Z].\K[A-Z0-9_-]*' < file.txt
_
J'ai ce code ci-dessus cependant, la sortie générée est seulement ceci 7I4543
et pas le tout 7I45432ZX
, qui est supposé être ma sortie attendue . Dois-je modifier ou ajouter quelque chose après _.\K
_ pour obtenir la valeur complète?
Essaye ça:
awk -F "*" '{ if ($1 == "PO") { lastTok = $(NF); getline; print lastTok "" $1;}}' input.txt
awk utilise "*" comme séparateur et affiche le dernier champ de la ligne commençant par PO suivi du premier champ de la ligne suivante.
La sortie est:
7I45432ZX
7I45432ZX
Si vous avez un fichier au format dos, vous devriez utiliser la commande dos2unix .
Essayez l'un des éléments suivants:
$ cat file.txt | Perl -e 's/\s//g && print "$_\n" for join("", <>) =~ /\*([\w\s]+)\*\*/g'
7I45432ZX
7I45432ZX
Je cherche fondamentalement un motif entre une étoile *
et deux étoiles **
. Une fois trouvé, je supprime simplement les espaces/retours chariot avant impression.
Par grep
et sed
:
grep -oPz '7I4543$\n^2ZX' file |sed '$!N;s/\n//'
7I45432ZX
7I45432ZX
grep
modèles 7I4543
et 2ZX
et tout ce qui les sépare sur plusieurs lignes. $
dans la commande grep pointe vers la fin de la ligne et ^
indique le début de la ligne.
sed
joint chaque paire de lignes à un linéaire. $
pointe la ligne actuelle, N
pointe vers la ligne suivante. puis remplacez/supprimez la nouvelle ligne \n
entre ces lignes.
-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.
Possible autre grep
s:
$ grep -oPz '7I4543$(^2ZX|\n)+'
$ grep -oPz '7I4543$\s^2ZX'
À travers GNU awk,
$ awk -v RS="PO" '/^\*/{gsub(/^.*\*/,"",$1); gsub(/\*.*$/,"",$2); print $1$2}' file
7I45432ZX
7I45432ZX
Installez pcregrep:
Sudo apt-get install pcregrep
puis lancez:
pcregrep -oM "PO.00.[A-Z][A-Z].\K[A-Z0-9_-].*\s+.*\*" < file.txt | tr -d '\n' | sed -e 's/\*\*/\n/g'
Sortie:
7I45432ZX
7I45432ZX
Voici l'explication de ce que le script fait. Tout d'abord, je devais faire en sorte que votre script original soit lu sur des sauts de ligne, puis le résultat serait ensuite affiché sur deux lignes distinctes, à moins que je ne le fasse également écrire sur des sauts de ligne. La dernière partie du script sed -e 's/\*\*/\n/g'
place un saut de ligne après chaque séparateur comme demandé par l'auteur de la question dans un commentaire relatif à cette réponse.
Si vous ne souhaitez pas installer Perl
ou quoi que ce soit d'autre et que vous souhaitiez utiliser de bons vieux outils de ligne standard coomand, vous pouvez utiliser quelque chose comme:
_sed '1 d
2 s/^PO\*00\*[A-Z][A-Z]\*\([A-Z0-9_-]*\)$/\1/
3 s/^\([A-Z0-9_-]*\)\*\*.*$/\1/' < file.txt
_
Cela suppose que
2
_ par _3
_ et _3
_ par _5
_ et ajouter _2 d
_ et _4 d
_ commandes sur des lignes supplémentaires par eux-mêmes;tr
comme suit: _| tr -d "\n\r"
_[Modifier]
sed
suppose également que vous avez des lignes de texte _UN*X
_. En outre, il semble y avoir une controverse quant à la rigueur des pattersn. Je pense que le PO suggère un certain degré de rigueur. De toute façon, les modèles sed
peuvent être facilement ajustés pour accepter les fins de ligne DOS
, par ex. en terminant par _\r*$
_.