Imprimer des lignes entre (et exclure) deux motifs

13

Je vais soumettre un formulaire en utilisant cURL, où une partie du contenu provient d'un autre fichier, sélectionné en utilisant sed

Si le param1modèle de correspondance de ligne d'un autre fichier utilise sed, la commande ci-dessous fonctionnera correctement:

curl -d param1="$(sed -n '/matchpattern/p' file.txt)" -d param2=value2 http://example.com/submit

Maintenant, allez au problème. Je souhaite afficher uniquement le texte entre 2 motifs correspondants à l'exclusion du motif correspondant lui-même.

Disons que file.txtcontient:

Bla bla bla
firstmatch
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
secondmatch
The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.

Actuellement, beaucoup de commandes "entre 2 motifs de correspondance" sedne supprimeront pas firstmatchet secondmatch.

Je veux que le résultat devienne:

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
lokomika
la source
stackoverflow.com/questions/17988756/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Réponses:

15

Voici une façon de procéder:

sed '1,/firstmatch/d;/secondmatch/,$d' 

Expliqué: De la première ligne à la ligne correspondant à la première correspondance , supprimez. De la ligne correspondant à la seconde correspondance à la dernière ligne, supprimez.

Jukka Matilainen
la source
6

En awk:

awk '
  $1 == "secondmatch" {print_me = 0}
  print_me {print}
  $1 == "firstmatch {print_me = 1}
'
glenn jackman
la source
Voici à propos des vitesses: unix.stackexchange.com/a/194662/16920
Léo Léopold Hertz
Et les vitesses?
glenn jackman
Je pense que SED est ici supérieur contrairement à AWK dans le temps.
Léo Léopold Hertz 준영
5

L'autre sedsolution échouera si elle firstmatchse produit sur la 1ère ligne 1 .

Restez simple, utilisez une seule plage et un regex 2 vide :
soit imprimez tout dans cette plage à l'exclusion des extrémités de la plage (impression automatique désactivée) 3 :

sed -n '/firstmatch/,/secondmatch/{//!p;}' infile

ou, plus court, supprimez tout ce qui n'est pas dans cette plage et supprimez également les extrémités de la plage:

sed '/firstmatch/,/secondmatch/!d;//d' infile


1: La raison étant que si la deuxième adresse est une expression rationnelle, la vérification de la correspondance de fin commencera par la ligne suivant la ligne qui correspond à la première adresse .
Par conséquent, /firstmatch/n'est jamais évalué pour la 1ère ligne de l'entrée, la sedsupprimera simplement car elle correspond au numéro de ligne 1,/RE/et passe à la 2ème ligne où elle vérifie si la ligne correspond/firstpattern/

2: Lorsqu'un REGEX est vide (c'est-à-dire //) sedse comporte comme si le dernier REGEX utilisé dans la dernière commande appliquée (soit comme adresse soit comme partie d'une commande de remplacement) était spécifié.

3: la ;}syntaxe est pour les sedimplémentations modernes ; avec les plus anciens, utilisez soit une nouvelle ligne au lieu du point-virgule, soit des expressions séparées, par exemplesed -n -e '/firstmatch/,/secondmatch/{//!p' -e '}' infile

don_crissti
la source
Pouvez-vous expliquer ce qui //se passe (à l'intérieur du {…})?
G-Man dit `` Réintègre Monica ''
Merci, mais tu es tombé dans mon piège. Je sais que cela //signifie la dernière expression régulière utilisée; de tout ce que j'ai lu, ça devrait être /secondmatch/. J'ai vérifié en testant que votre commande fonctionne, et j'ai donc conclu qu'elle fonctionne comme /firstmatch|secondmatch/(ce que vous avez confirmé), mais je ne trouve aucune documentation (pas même le document POSIX auquel vous avez lié ou le GNU sed manuel ) qui décrit ce comportement. … (Suite)
G-Man dit «Réintègre Monica»
(Suite)… Expériences divertissantes: (I) Dans sed: (1) Si je le fais /first/,4, alors je me //comporte comme /first/. (2) Si je le fais 2,/second/, //obtient alors une erreur «aucune expression régulière précédente». (Je trouve que c'est un échec flagrant de suivre le comportement spécifié.) (3) L'ajout --posixne change rien à ce qui précède. (II) Dans d'autres programmes: (4) Dans vi, après /first/,/second/, des //actes comme /second/(et les autres formes sont également des implémentations rationnelles de la règle documentée). … (Suite)
G-Man dit «Réintègre Monica»
(Suite)… (5) ne  awksemble avoir aucune notion de «la dernière RE utilisée»; //fait référence au non-caractère avant ou après n'importe quel caractère. (Je vous invite à essayer echo -- | awk '{ gsub(//, "cha"); print }'.)
G-Man dit 'Reinstate Monica'
Donc, vous lisez "le dernier REGEX utilisé dans la dernière commande" comme "le dernier REGEX (s) utilisé dans la dernière commande" et donc vous avez (correctement) deviné que cela signifiait /first|second/. Quel chanceux êtes-vous. Je mentionne les autres programmes pour démontrer qu'il ne s'agit pas d'une convention regex à l'échelle du système. Celui qui l'a ajouté sedn'a pas pris la peine de l'ajouter vim, où cela aurait été tout aussi logique. :-) ⁠
G-Man dit 'Réintègre Monica'