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
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.
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.
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
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 ...