web-dev-qa-db-fra.com

Programmation de script Bash: comment faire correspondre un modèle dans une chaîne?

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?

4
user74775

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 .

1
Lety

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.

1
Sylvain Pineau

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 greps:

$ grep -oPz '7I4543$(^2ZX|\n)+'
$ grep -oPz '7I4543$\s^2ZX'
1
αғsнιη

À travers GNU awk,

$ awk -v RS="PO" '/^\*/{gsub(/^.*\*/,"",$1); gsub(/\*.*$/,"",$2); print $1$2}' file
7I45432ZX
7I45432ZX
0
Avinash Raj

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.

0
karel

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

  • votre fichier contient 3 lignes. Si votre fichier contient 5 lignes contenant les informations pertinentes, lignes 1, 3 et 5, vous devrez remplacer _2_ par _3_ et _3_ par _5_ et ajouter _2 d_ et _4 d_ commandes sur des lignes supplémentaires par eux-mêmes;
  • vous pouvez vivre avec le saut de ligne dans la sortie. Si cela ne vous convient pas, dirigez la sortie vers tr comme suit: _| tr -d "\n\r"_

[Modifier]

  • La partie 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*$_.
0
Run CMD