J'essaie de sortir une chaîne qui contient tout entre deux mots d'une chaîne:
contribution:
"Here is a String"
production:
"is a"
En utilisant:
sed -n '/Here/,/String/p'
inclut les points de terminaison, mais je ne souhaite pas les inclure.
Here is a Here String
? OuI Hereby Dub Thee Sir Stringy
?sed
FAQ courante est "comment extraire du texte entre des lignes particulières"; c'est stackoverflow.com/questions/16643288/…Réponses:
la source
echo "Here is a one is a String" | sed -e 's/one is\(.*\)String/\1/'
. Si vous voulez juste la partie entre « est » et « String », alors vous devez faire la regex correspondre à la ligne entière:sed -e 's/.*one is\(.*\)String.*/\1/'
. Dans sed,s/pattern/replacement/
dites "remplacez" remplacement "par" motif "sur chaque ligne". Cela ne changera que tout ce qui correspond à "pattern", donc si vous voulez qu'il remplace la ligne entière, vous devez faire correspondre "pattern" à toute la ligne.Here is a String Here is a String
GNU grep peut également prendre en charge les anticipations et les rétrospectives positives et négatives: pour votre cas, la commande serait:
S'il existe plusieurs occurrences de
Here
etstring
, vous pouvez choisir si vous voulez faire correspondre le premierHere
et le dernierstring
ou les faire correspondre individuellement. En termes de regex, il est appelé correspondance gourmande (premier cas) ou correspondance non gourmande (deuxième cas)la source
-P
option de GNU grep n'existe pas dans legrep
BSD inclus dans *, ni dans ceux qui sont fournis avec n'importe quel SVR4 (Solaris, etc.). Dans FreeBSD, vous pouvez installer ledevel/pcre
port qui inclutpcregrep
, qui prend en charge PCRE (et look-ahead / behind). Les anciennes versions d'OSX utilisaient GNU grep, mais dans OSX Mavericks,-P
est dérivé de la version de FreeBSD, qui n'inclut pas l'option.Here is a string a string
, les deux" is a "
et" is a string a "
sont des réponses valides (ignorez les guillemets), conformément aux exigences de la question. Cela dépend de vous lequel de ceux-ci vous voulez et la réponse peut être différente en conséquence. Quoi qu'il en soit, pour votre condition, cela fonctionnera:echo "Here is a string a string" | grep -o -P '(?<=Here).*?(?=string)'
echo $'Here is \na string' | grep -zoP '(?<=Here)(?s).*(?=string)'
La réponse acceptée ne supprime pas le texte qui pourrait être avant
Here
ou aprèsString
. Cette volonté:La principale différence est l'ajout de
.*
immédiatement avantHere
et aprèsString
.la source
*
quantificateur, entreHere
etString
, non gourmand (ou paresseux). Cependant, le type de regex utilisé par sed ne prend pas en charge les quantificateurs paresseux (?
immédiatement après.*
) selon cette question Stackoverflow. Habituellement, pour implémenter un quantificateur paresseux, vous correspondriez simplement à tout sauf le jeton que vous ne vouliez pas faire correspondre, mais dans ce cas, il n'y a pas qu'un seul jeton, mais plutôt une chaîne entièreString
..
ne correspond pas aux sauts de ligne. Si vous souhaitez faire correspondre les sauts de ligne, vous pouvez les remplacer.
par quelque chose comme[\s\s]
.Vous pouvez supprimer des chaînes dans Bash seul:
Et si vous avez un grep GNU qui inclut PCRE , vous pouvez utiliser une assertion de largeur nulle:
la source
Grâce à GNU awk,
grep avec le paramètre
-P
( perl-regexp ) prend en charge\K
, ce qui aide à supprimer les caractères précédemment correspondants. Dans notre cas, la chaîne précédemment correspondante étaitHere
donc supprimée de la sortie finale.Si vous voulez que la sortie soit,
is a
vous pouvez essayer ce qui suit,la source
echo "Here is a string dfdsf Here is a string" | awk -v FS="(Here|string)" '{print $2}'
il revient uniquementis a
au lieu de devrait êtreis a is a
@Avinash RajSi vous avez un long fichier avec de nombreuses occurrences multilignes, il est utile de commencer par imprimer des lignes numériques:
la source
-n
option danscat
doit être omise.cat
peut être entièrement omis;sed
sait lire un fichier ou une entrée standard.Cela pourrait fonctionner pour vous (GNU sed):
Ceci présente chaque représentation de texte entre deux marqueurs (dans ce cas
Here
etString
) sur une nouvelle ligne et préserve les nouvelles lignes dans le texte.la source
Toutes les solutions ci-dessus présentent des lacunes où la dernière chaîne de recherche est répétée ailleurs dans la chaîne. J'ai trouvé préférable d'écrire une fonction bash.
la source
Vous pouvez utiliser deux commandes s
Fonctionne aussi
la source
Pour comprendre la
sed
commande, nous devons la construire étape par étape.Voici votre texte original
Essayons de supprimer la
Here
chaîne avec l's
option ubstition danssed
À ce stade, je crois que vous seriez en mesure d'éliminer
String
aussi bienMais ce n'est pas la sortie souhaitée.
Pour combiner deux commandes sed, utilisez l'
-e
optionJ'espère que cela t'aides
la source
Vous pouvez utiliser
\1
(voir http://www.grymoire.com/Unix/Sed.html#uh-4 ):Le contenu entre crochets sera stocké sous forme de
\1
.la source
Problème. Mes messages Claws Mail stockés sont emballés comme suit et j'essaie d'extraire les lignes d'objet:
Par A2 dans ce fil, comment utiliser sed / grep pour extraire du texte entre deux mots? la première expression, ci-dessous, "fonctionne" tant que le texte correspondant ne contient pas de nouvelle ligne:
Cependant, malgré avoir essayé de nombreuses variantes (
.+?; /s; ...
), je n'ai pas pu les faire fonctionner:Solution 1.
Par Extraire du texte entre deux chaînes sur des lignes différentes
qui donne
Solution 2. *
Par Comment puis - je remplacer un saut de ligne (\ n) en utilisant sed?
remplacera les nouvelles lignes par un espace.
Enchaîner cela avec A2 dans Comment utiliser sed / grep pour extraire du texte entre deux mots? , on a:
qui donne
Cette variante supprime les doubles espaces:
donnant
la source