AWK
Utilisation de GNU awk ou mawk:
$ awk '$1~"^"word{printf("--\n%s",$0)}' word='are' RS='--\n' infile
--
are you happy
--
are(you hungry
too
Ceci définit le mot variable sur le mot correspondant au début de l'enregistrement et RS (séparateur d'enregistrement) sur '-' suivi d'une nouvelle ligne \n
. Ensuite, pour tout enregistrement commençant par le mot à rechercher ( $1~"^"word
), imprimez un enregistrement mis en forme. Le format est un "-" de départ avec une nouvelle ligne avec l'enregistrement exact trouvé.
GREP
Utiliser (GNU pour l’ -z
option) grep:
grep -Pz -- '--\nare(?:[^\n]*\n)+?(?=--|\Z)' infile
grep -Pz -- '(?s)--\nare.*?(?=\n--|\Z)\n' infile
grep -Pz -- '(?s)--\nare(?:(?!\n--).)*\n' infile
Description (s) Pour les descriptions suivantes, l'option PCRE (?x)
est utilisée pour ajouter (beaucoup) des explications de commentaires (et d'espaces) en ligne avec l'expression rationnelle réelle (de travail). Si les commentaires (et la plupart des espaces) (jusqu'à la nouvelle ligne) sont supprimés, la chaîne résultante reste la même expression régulière. Cela permet de décrire la regex en détail dans le code de travail. Cela facilite grandement la maintenance du code.
Option 1 regex (?x)--\nare(?:[^\n]*\n)+?(?=--|\Z)
(?x) # match the remainder of the pattern with the following
# effective flags: x
# x modifier: extended. Spaces and text after a #
# in the pattern are ignored
-- # matches the characters -- literally (case sensitive)
\n # matches a line-feed (newline) character (ASCII 10)
are # matches the characters are literally (case sensitive)
(?: # Non-Capturing Group (?:[^\n]*\n)+?
[^\n] # matches non-newline characters
* # Quantifier — Matches between zero and unlimited times, as
# many times as possible, giving back as needed (greedy)
\n # matches a line-feed (newline) character (ASCII 10)
) # Close the Non-Capturing Group
+? # Quantifier — Matches between one and unlimited times, as
# few times as possible, expanding as needed (lazy)
# A repeated capturing group will only capture the last iteration.
# Put a capturing group around the repeated group to capture all
# iterations or use a non-capturing group instead if you're not
# interested in the data
(?= # Positive Lookahead (?=--|\Z)
# Assert that the Regex below matches
# 1st Alternative --
-- # matches the characters -- literally (case sensitive)
| # 2nd Alternative \Z
\Z # \Z asserts position at the end of the string, or before
# the line terminator right at the end of the
# string (if any)
) # Closing the lookahead.
Option 2 regex (?sx)--\nare.*?(?=\n--|\Z)\n
(?sx) # match the remainder of the pattern with the following eff. flags: sx
# s modifier: single line. Dot matches newline characters
# x modifier: extended. Spaces and text after a # in
# the pattern are ignored
-- # matches the characters -- literally (case sensitive)
\n # matches a line-feed (newline) character (ASCII 10)
are # matches the characters are literally (case sensitive)
.*? # matches any character
# Quantifier — Matches between zero and unlimited times,
# as few times as possible, expanding as needed (lazy).
(?= # Positive Lookahead (?=\n--|\Z)
# Assert that the Regex below matches
# 1st Alternative \n--
\n # matches a line-feed (newline) character (ASCII 10)
-- # matches the characters -- literally.
| # 2nd Alternative \Z
\Z # \Z asserts position at the end of the string, or
# before the line terminator right at
# the end of the string (if any)
) # Close the lookahead parenthesis.
\n # matches a line-feed (newline) character (ASCII 10)
Option 3 regex (?xs)--\nare(?:(?!\n--).)*\n
(?xs) # match the remainder of the pattern with the following eff. flags: xs
# modifier x : extended. Spaces and text after a # in are ignored
# modifier s : single line. Dot matches newline characters
-- # matches the characters -- literally (case sensitive)
\n # matches a line-feed (newline) character (ASCII 10)
are # matches the characters are literally (case sensitive)
(?: # Non-capturing group (?:(?!\n--).)
(?! # Negative Lookahead (?!\n--)
# Assert that the Regex below does not match
\n # matches a line-feed (newline) character (ASCII 10)
-- # matches the characters -- literally
) # Close Negative lookahead
. # matches any character
) # Close the Non-Capturing group.
* # Quantifier — Matches between zero and unlimited times, as many
# times as possible, giving back as needed (greedy)
\n # matches a line-feed (newline) character (ASCII 10)
sed
$ sed -nEe 'bend
:start ;N;/^--\nare/!b
:loop ;/^--$/!{p;n;bloop}
:end ;/^--$/bstart' infile
--
à la fin de chaque enregistrement, tandis que la question a--
au début de chaque enregistrement. Peut-être que l’utilisation de aprintf("--\n%s",$0)
est une solution possible (notez que cela n’utilise pas l’OFS et qu’il pourrait rester à la valeur par défaut).C'est une vieille question, je sais, mais ça me fait mal de voir toute cette boucle, cette ramification et ce motif qui jongle quand un simple
fait la même chose de façon naturelle.
sed
est un éditeur de flux linéaire; ainsi, si vous avez besoin de plusieurs lignes, rassemblez ces lignes dans l'espace réservé avecH
et sur le paragraphe mark (^--$
) ex
changez les tampons et testez si le paragraphe doit être imprimé (^--\nare
une--
ligne suivie d'une ligne commençant parare
). Lex
précharge déjà l'espace d'attente avec la marque de paragraphe.Vous n'avez pas besoin d'outils GNU avec des extensions sauvages, vous n'avez pas besoin de compétences en programmation, vous vous contentez de vous engager
sed
.la source
Je reviendrai plus tard pour des explications de travail ..
la source
En examinant votre question, j’ai pensé qu’il devrait être possible de la résoudre à l'aide de
grep
+ PCRE .(?s)
) et lookahead (?!...
).méthode grep n ° 1
Comment ça fonctionne
commutateurs grep-P
- extensions PCRE activées-z
- traite l'entrée avec plusieurs lignes, en utilisant NUL à la place de\n
(nouvelles lignes)-o
- montrer seulement les matches--\nare([^\n]*\n)+?(?=--|\Z)
are
, puis d'une continuation de zéro ou de plusieurs caractères autres que la nouvelle ligne - ou - une nouvelle ligne.+?
match correspondra à 1 ou plus, mais est non-gourmand, donc il ne continuera pas agressivement.(?=--|\Z)
gardes de la fin du bloc recherchent le prochain double tiret--
ou la fin du fichier (\Z
).méthode grep # 2
Cette méthode utilise le modificateur DOTALL inline pour faire
.
correspondre les nouvelles lignes (`n`).Comment ça fonctionne
commutateurs grep-P
- extensions PCRE activées-z
- traite l'entrée avec plusieurs lignes, en utilisant NUL à la place de\n
(nouvelles lignes)-o
- montrer seulement les matches(?s)
- Modificateur en ligne DOTALL - Tous les points doivent correspondre à la nouvelle ligne--\nare
- correspond à une nouvelle ligne suivie deare
((?!\n--).)+\n
- fait correspondre les caractères.
tant que le lookahead(?!\n--)
ne rencontre pas un\n--
. Ce bloc entier de correspondance doit être d' au moins un ou plusieurs (+
) et suivi d'un saut de ligne,\n
.méthode grep n ° 3 (d'origine)
Voici une
grep
solution qui utilise l'extension PCRE (-P
). Cette méthode a fonctionné pour tous les exemples fournis, elle échouerait avec des exemples comme celui-ci:Mais sinon, dans la plupart des cas, je pourrais concevoir de devoir lutter.
Comment ça fonctionne
commutateurs grep-P
- extensions PCRE activées-z
- traite l'entrée avec plusieurs lignes, en utilisant NUL à la place de\n
(nouvelles lignes)-o
- montrer seulement les matches'--\nare[^\r\n]+[^-]+'
are
.are
allumée jusqu'à ce qu'une nouvelle ligne soit rencontrée.Références
la source
are(you hungry
et une seconde ligne detoo-maybe?
are
lignes mais je n'en avais pas inséré un dans les lignes qui l'ont suivi. Le?
ne pas vraiment entrer en jeu, vous êtes juste jeter les caractères supplémentaires pour le rendre plus compliqué?Are
:-) .....awk
solution que vous avez présentée, soit 8- (.grep -Pzo -- '--\nare([^\n]*\n)+?(?=--|\Z)' infile
:-P