web-dev-qa-db-fra.com

grep: correspond à tous les caractères jusqu'au premier espace vide (non compris)

J'ai un fichier texte au format suivant:

characters(that I want to keep) (space) characters(that I want to remove)

Ainsi, par exemple:

foo garbagetext
hello moregarbage
keepthis removethis
(etc.)

J'essayais donc d'utiliser la commande grep sous Linux pour ne conserver que les caractères de chaque ligne et sans inclure le premier espace vide. J'ai essayé de nombreuses tentatives telles que:

grep '*[[:space:]]' text1.txt > text2.txt
grep '*[^\s]' text1.txt > text2.txt
grep '/^[^[[:space:]]]+/' text1.txt > text2.txt

essayant de reconstituer des exemples différents, mais je n'ai pas eu de chance. Ils produisent tous un blanc text2.txt fichier. Je suis nouveau dans ce domaine. Qu'est-ce que je fais mal?

*ÉDITER:

Les parties que je souhaite conserver comprennent des majuscules. Je veux donc garder tous les caractères/tous jusqu'à et ne pas inclure l'espace vide (en supprimant tout à partir de l'espace vide) dans chaque ligne.

**ÉDITER:

Le texte poubelle (que je veux supprimer) peut contenir n'importe quoi, y compris des espaces, des caractères spéciaux, etc. Ainsi, par exemple:

AA rough, cindery lava [n -S]

Après avoir exécuté grep -o '[^ ]*' text1.txt > text2.txt, la ligne ci-dessus devient:

AA
rough,
cindery
lava
[n
-S]

dans text2.txt. (Tout ce que je veux garder c'est AA)


SOLUTION (fournie par Rohit Jain avec une contribution supplémentaire de beny23):

 grep -o '^[^ ]*' text1.txt > text2.txt
19
lord_sneed

Vous mettez un quantificateur * au mauvais endroit.

Essayez plutôt ceci: -

grep '^[^\s]*' text1.txt > text2.txt

ou encore mieux: -

grep '^\S*' text1.txt > text2.txt  

\S signifie correspondance non blanc caractère. Et ancre ^ est utilisé pour faire correspondre au début de la ligne.

30
Rohit Jain

Je réalise que la solution grep a depuis longtemps été résolue, mais pour les générations futures, je voudrais noter qu'il existe au moins deux autres solutions pour cette situation particulière, toutes deux plus efficaces que grep.

Comme vous n'effectuez aucune correspondance de modèle de texte complexe, en prenant simplement la première colonne délimitée par un espace, vous pouvez utiliser certains des utilitaires basés sur des colonnes, tels que awk ou cut.

en utilisant awk

$ awk '{print $1}' text1.txt > text2.txt

en utilisant la coupe

$ cut -f1 -d' ' text1.txt > text2.txt

Repères sur un fichier de ~ 1,1 Mo

$ time grep -o '^[^ ]*' text1.txt > text2.txt

real    0m0.064s
user    0m0.062s
sys     0m0.001s
$ time awk '{print $1}' text1.txt > text2.txt

real    0m0.021s
user    0m0.017s
sys     0m0.004s
$ time cut -f1 -d' ' text1.txt > text2.txt

real    0m0.007s
user    0m0.004s
sys     0m0.003s

awk est environ 3 fois plus rapide que grep, et cut est environ 3 fois plus rapide que cela. Encore une fois, il n'y a pas beaucoup de différence pour ce petit fichier pour une seule exécution, mais si vous écrivez un script, par exemple, pour une réutilisation, ou si vous le faites souvent sur des fichiers volumineux, vous pourriez apprécier l'efficacité supplémentaire.

13
Steve

Suite à la réponse de @Steve, si vous souhaitez utiliser un séparateur différent (par exemple une virgule), vous pouvez le spécifier en utilisant -F. Cela sera utile si vous souhaitez que le contenu de chaque ligne jusqu'à la première virgule, comme lorsque vous essayez de lire la valeur du premier champ dans un fichier csv.

$ awk -F "," '{print $1}' text1.txt > text2.txt
0
TDS

J'utilise beaucoup egrep pour aider à "coloriser" les lignes de journal, donc je suis toujours à la recherche d'une nouvelle tournure sur l'expression régulière. Pour moi, ce qui précède fonctionne mieux en ajoutant un\W comme ceci:

$ egrep --color '^\S*\W|bag' /tmp/barf -o
foo
bag
hello
bag
keepthis
(etc.)

Le problème est que mes fichiers journaux sont presque toujours horodatés, j'ai donc ajouté une ligne au fichier d'exemple:

2013-06-11 date stamped line

et puis ça ne marche pas si bien. Je suis donc revenu à mon expression régulière précédente:

egrep --color '^\w*\b|bag' /tmp/barf

mais les lignes non datées ont révélé des problèmes avec que. Il est difficile de voir cela sans colorisation ...

0
MarkHu