Comment utiliser sed/grep pour extraire du texte entre deux mots?
10 réponses
grep Simple peut également soutenir un regard positif et négatif et un regard en arrière: Pour votre cas, la commande serait:
echo "Here is a string" | grep -o -P '(?<=Here).*(?=string)'
vous pouvez rayer des cordes dans Bash seul:
$ foo="Here is a String"
$ foo=${foo##*Here }
$ echo "$foo"
is a String
$ foo=${foo%% String*}
$ echo "$foo"
is a
$
et si vous avez un GNU grep qui inclut PCRE , vous pouvez utiliser une assertion de largeur zéro:
$ echo "Here is a String" | grep -Po '(?<=(Here )).*(?= String)'
is a
la réponse acceptée ne supprime pas le texte qui pourrait être avant Here
ou après String
. Ce sera:
sed -e 's/.*Here\(.*\)String.*//'
la principale différence est l'ajout de .*
immédiatement avant Here
et après String
.
par GNU awk,
$ echo "Here is a string" | awk -v FS="(Here|string)" '{print }'
is a
grep avec -P
( perl-regexp ) paramètre prend en charge \K
, ce qui aide à rejeter les caractères précédemment appariés. Dans notre cas, la chaîne précédemment appariée était Here
donc elle a été écartée de la sortie finale.
$ echo "Here is a string" | grep -oP 'Here\K.*(?=string)'
is a
$ echo "Here is a string" | grep -oP 'Here\K(?:(?!string).)*'
is a
si vous voulez que la sortie soit is a
alors vous pouvez essayer ce qui suit,
$ echo "Here is a string" | grep -oP 'Here\s*\K.*(?=\s+string)'
is a
$ echo "Here is a string" | grep -oP 'Here\s*\K(?:(?!\s+string).)*'
is a
si vous avez un long fichier avec de nombreuses ocurrences multilignes, il est utile de commencer par imprimer les lignes du numéro:
cat -n file | sed -n '/Here/,/String/p'
cela pourrait marcher pour vous (GNU sed):
sed '/Here/!d;s//&\n/;s/.*\n//;:a;/String/bb;$!{n;ba};:b;s//\n&/;P;D' file
présente chaque représentation de texte entre deux repères (dans ce cas Here
et String
) sur une ligne nouvelle et préserve les lignes nouvelles dans le texte.
toutes les solutions ci-dessus présentent des lacunes lorsque la dernière chaîne de recherche est répétée ailleurs dans la chaîne. J'ai trouvé mieux d'écrire une fonction de bash.
function str_str {
local str
str="${1#*}"
str="${str%%*}"
echo -n "$str"
}
# test it ...
mystr="this is a string"
str_str "$mystr" "this " " string"
vous pouvez utiliser (se référer à http://www.grymoire.com/Unix/Sed.html#uh-4 ):
echo "Hello is a String" | sed 's/Hello\(.*\)String//g'
le contenu qui se trouve à l'intérieur des crochets sera stocké sous la forme .
problème. mes messages stockés sont emballés comme suit, et j'essaie d'extraire les lignes objet:
Subject: [SLC38A9 lysosomal arginine sensor; mTORC1 pathway] Key molecular
link in major cell growth pathway: Findings point to new potential
therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 Is
Required to Efflux Essential Amino Acids from Lysosomes and Use Protein as
a Nutrient] [Re: Nutrient sensor in key growth-regulating metabolic pathway
identified [Lysosomal amino acid transporter SLC38A9 signals arginine
sufficiency to mTORC1]]
Message-ID: <20171019190902.18741771@VictoriasJourney.com>
Par A2 dans ce fil, Comment utiliser sed/grep pour extraire le texte entre les deux mots? la première expression, ci-dessous, "fonctionne" tant que le texte apparié ne contient pas de nouvelle ligne:
grep -o -P '(?<=Subject: ).*(?=molecular)' corpus/01
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway] Key
cependant, malgré l'essai de nombreuses variantes ( .+?; /s; ...
grep -o -P '(?<=Subject: ).*(?=link)' corpus/01
grep -o -P '(?<=Subject: ).*(?=therapeutic)' corpus/01
etc.
la Solution 1.
Per extrait de texte entre deux chaînes sur des lignes différentes
sed -n '/Subject: /{:a;N;/Message-ID:/!ba; s/\n/ /g; s/\s\s*/ /g; s/.*Subject: \|Message-ID:.*//g;p}' corpus/01
qui donne
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway] Key molecular link in major cell growth pathway: Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 Is Required to Efflux Essential Amino Acids from Lysosomes and Use Protein as a Nutrient] [Re: Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
la Solution 2.*
Per Comment puis-je remplacer une newline (\n) en utilisant sed?
sed ':a;N;$!ba;s/\n/ /g' corpus/01
remplacera newlines par un espace.
enchaîner avec A2 dans comment utiliser sed/grep pour extraire du texte entre deux mots? , nous obtenons:
sed ':a;N;$!ba;s/\n/ /g' corpus/01 | grep -o -P '(?<=Subject: ).*(?=Message-ID:)'
qui donne
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway] Key molecular link in major cell growth pathway: Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 Is Required to Efflux Essential Amino Acids from Lysosomes and Use Protein as a Nutrient] [Re: Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
cette variante supprime les espaces doubles:
sed ':a;N;$!ba;s/\n/ /g; s/\s\s*/ /g' corpus/01 | grep -o -P '(?<=Subject: ).*(?=Message-ID:)'
donnant
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway] Key molecular link in major cell growth pathway: Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 Is Required to Efflux Essential Amino Acids from Lysosomes and Use Protein as a Nutrient] [Re: Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]