Contribution:
19. "foo foo" (bar bar) (19) raboof
"foo foo" raboof
Production attendue:
"foo foo" (bar bar) (19)
"foo foo"
Comme vous pouvez le constater, j'aimerais conserver les guillemets et les parenthèses.
Tout ce qui ne se trouve pas entre guillemets ou parenthèses doit être supprimé.
Utiliser python
:
#!/usr/bin/env python2
import re, sys
with open(sys.argv[1]) as f:
for line in f:
parts = line.split()
for i in parts:
if re.search(r'^[("].*[)"]$', i):
print i,
print '\n'.lstrip()
Sortie:
"foo" (bar) (19)
"foo"
Chaque ligne est lue et les parties séparées par des espaces sont enregistrées dans une liste appelée parts
Ensuite, en utilisant la fonction re
du module search
du module, nous avons trouvé les parties commençant par "
ou (
et se terminant par "
ou )
.
Comment exécuter:
Enregistrez le script sous le nom, par exemple. script.py
. Maintenant, vous pouvez le lancer de deux manières:
Rendez-le exécutable par chmod u+x /path/to/script.py
et exécutez-le en tant que /path/to/script.py /path/to/file.txt
c'est-à-dire entrez le fichier file.txt
en tant que premier argument. Si le script et le fichier se trouvent dans le même répertoire, à partir de ce répertoire ./script.py file.txt
Vous pouvez l'exécuter sans le rendre exécutable, exécutez-le en tant que python2 script.py file.txt
.
Réponse à la question modifiée:
#!/usr/bin/env python2
import re, sys
with open(sys.argv[1]) as f:
for line in f:
print ''.join(re.findall(r'(?:(?<=\s)["(].*[")](?=\s|$)|(?<=^)["(].*[")](?=\s|$))', line))
Sortie:
"foo foo" (bar bar) (19)
"foo foo"
Nouvelle version (espaces autorisés entre ()
ou ""
):
Essayez la commande Perl
ci-dessous (crédits: @ steeldriver )
Perl -ne 'printf "%s\n", join(" " , $_ =~ /["(].*?[)"]/g)'
Version initiale (aucun espace entre ()
ou ""
)
Vous pouvez essayer ce qui suit Perl
oneliner:
$ Perl -ne '@a=split(/\s+/, $_); for (@a) {print "$_ " if /[("].*?[)"]/ };print"\n"' file
Une autre option python:
#!/usr/bin/env python3
import sys
match = lambda ch1, ch2, w: all([w.startswith(ch1), w.endswith(ch2)])
for l in open(sys.argv[1]).read().splitlines():
matches = [w for w in l.split() if any([match("(", ")", w), match('"', '"', w)])]
print((" ").join(matches))
Copiez le script dans un fichier vide, enregistrez-le sous le nom filter.py
Exécutez-le avec la commande:
python3 /path/to/filter.py <file>
Si nous supposons il y a un caractère fermant sur chaque ouvrant caractère: '('
et '"'
(nous devrions supposer que , car sinon le fichier serait incorrect ou la question devrait mentionner un ensemble de règles plus complexe dans le cas de parenthèses ou de guillemets "imbriqués"), le code ci-dessous devrait également faire le travail:
#!/usr/bin/env python3
import sys
chunks = lambda l: [l[i:i + 2] for i in range(0, len(l), 2)]
for l in open(sys.argv[1]).read().splitlines():
words = chunks([i for i in range(len(l)) if l[i] in ['(', ')', '"']])
print((" ").join([l[w[0]:w[1]+1] for w in words]))
Il répertorie les caractères de la liste: ['(', ')', '"']
, crée des fragments de deux correspondances trouvées et imprime ce qui se trouve dans la plage de chaque couple:
19. "foo" (bar bar) (blub blub blub blub) (19) raboof
"foo" raboof
affichera alors:
"foo" (bar bar) (blub blub blub blub) (19)
"foo"
L'utilisation est exactement comme le premier script.
Plusieurs "déclencheurs" peuvent être facilement ajoutés en ajoutant les deux côtés (caractère de début et de fin de la chaîne ou de la section à "conserver") dans la liste:
['(', ')', '"']
dans la ligne:
words = chunks([i for i in range(len(l)) if l[i] in ['(', ')', '"']])
Comme script Perl
:
$filename=$ARGV[0];
if (open(my $fh, '<:encoding(UTF-8)', $filename)) {
while (my $match = <$fh>) {
while ($match =~ /((\(.*?[^)]\))|(".*?"))/g) {
print "$1 ";
}
print "\n"
}
}
Ou comme Perl
one-liner:
Perl -ne 'while (/((\(.*?[^)]\))|(".*?"))/g) {print "$1 ";} print "\n"' file
Sortie
"foo foo" (bar bar) (19)
"foo foo"
C'était le tâche originale :
Entrée:
- "foo" (bar) (19)
raboof "foo" raboof
Résultat attendu:
"foo" (bar) (19)
"foo"
Utiliser Perl
:
Perl -pe '@elements=( split (/\s/) );
for $element (@elements) {
if ($element!~/^"|\(/ and $element!~/"|\($/) {
s/$element//
}
s/^\s+//;
s/\s+$/\n/
};' file
ou comme one-liner:
Perl -pe '@elements=( split (/\s/) ); for $element (@elements) { if ($element!~/^"|\(/ and $element!~/"|\($/) { s/$element// } s/^\s+//; s/\s+$/\n/ };' file
Sortie:
"foo" (bar) (19)
"foo"
Si vous (ou une autre personne ayant un problème similaire qui lit ceci) n'avez pas besoin de conserver les nouvelles lignes, les opérations suivantes fonctionneraient:
grep -Eo '"[^"]*"|\([^)]*\)'
Pour l'entrée
19. "foo foo" (bar bar) (19) raboof
"foo foo" raboof
il produit une sortie
"foo foo"
(bar bar)
(19)
"foo foo"
Si vous avez besoin de nouvelles lignes, vous pouvez utiliser certaines astuces, par exemple. cette:
sed 's/$/\$/' \
| grep -Eo '"[^"]*"|\([^)]*\)|\$$' \
| tr '\n$' ' \n' \
| sed 's/^ //'
Le premier sed
ajoute un $
à la fin de chaque ligne. (Vous pouvez utiliser n'importe quel caractère pour cela.) Le second est presque identique à grep
comme ci-dessus, mais correspond également à $
à la fin d'une ligne. Il correspond donc à chaque fin de ligne. Le tr
transforme les nouvelles lignes en espaces et les dollars en nouvelles lignes. Mais puisque la sortie précédente tr
avait $
suivie de nouvelle ligne, la sortie suivante comportera une nouvelle ligne suivie d'un espace. La version finale sed
supprime ces espaces.
Un autre Perl
:
$ Perl -nle 'print join " ", $_ =~ /".*?"|\(.*?\)/g' file
"foo foo" (bar bar) (19)
"foo foo"
Ci-dessous, le simple code python fera ce travail.
import re
with open('file') as f:
reg = re.compile(r'"[^"]*"|\([^)]*\)')
for line in f:
print(' '.join(reg.findall(line)))
Et un autre par Perl qui utilise seulement regex,
$ Perl -pe 's/(?:"[^"]*"|\([^)]*\))(*SKIP)(*F)|\S//g;s/^\h+|\h+$|(\h)+/\1/g' file
"foo foo" (bar bar) (19)
"foo foo"
PHP serait:
if (preg_match_all('/"(?:[^"\\\\]+|\\\\.)+"|\\([^)]+\\)/', $input, $matches)) {
echo implode(' ', $matches[0]);
}
Cela gère également correctement les caractères échappés dans les chaînes entre guillemets (par exemple, "Test \"string\""
est traité comme une chaîne.