Détection de modèle en fin de ligne avec grep


65

Si je fais:

$ ls -R
.:
4Shared/  Cloud/

./4Shared:
UFAIZLV2R7.part3.rar

./Cloud:
UFAIZLV2R7.part2.rar.part
UFAIZLV2R7.part1.rar.part
UFAIZLV2R7.part4.rar.part

Si je veux lister .raruniquement les fichiers et que j'utilise grep , les .rar.partfichiers seront également affichés , ce qui n'est pas mon souhait.
Je résous ceci en utilisant findou ls **/*.rarcomme dit dans ce fil et ils fonctionnent bien, mais je voudrais savoir s'il est possible de le faire via grep.

J'ai essayé (en pensant à EOL):

ls -R | grep ".rar\n"

sans résultat.
Je pense que le problème réside dans le fait de savoir si le greping se trouve au bout de la ligne , mais je ne suis pas sûr.

Toute aide ici, s'il vous plaît?


Pourquoi voudriez-vous utiliser grepdans ce cas? Pourquoi ne pas find?
devnull

1
@devnull, savoir comment détecter des modèles qui ne sont qu'en fin de ligne pourrait être utile dans de nombreux cas. Par exemple: portabilité, utilisation dans les routeurs avec Linux trop simpliste intégré, utilisation avec UnxUtils pour Windows (sa findcommande est en conflit avec celle de Windows) et ... apprentissage ;-). La question ne concerne pas "Répertorier les fichiers dans un répertoire" (il ne s'agit que d'un exemple personnalisé), mais plutôt "Comprendre l'utilisation de la commande grep"
Sopalajo de Arrierez

1
Honnêtement, si vous comptez sur la fin d'une ligne pour être votre séparateur, vous devriez utiliser ls -1R.
mikeserv

1
Et tu n'as même pas besoin grep. Voir ma réponse.
mikeserv

@ mikeserv, que pourrait-il se passer sans le -1Rcommutateur? Apparemment, les résultats sont les mêmes.
Sopalajo de Arrierez

Réponses:


89

L' $ancre correspond à la fin d'une ligne.

ls -R | grep '\.rar$'

Vous pouvez également utiliser findpour cela:

find . -name '*.rar'

Je n'ai pas réalisé le "." doit être échappé dans grep. Est-ce traité comme un joker?
thebunnyrules

1
@thebunnyrules "." en regex signifie l'un de n'importe quel caractère.
Jordanie

10

En plus de votre question, veuillez noter que .rarcela ne correspond pas seulement à ".rar" mais à chaque caractère (y compris .) précédant le rar. Dans ce cas, probablement pas un problème mais .doit être échappé dans les expressions rationnelles.

ls -R | grep "\.rar$"

Voulez-vous dire que .ascc'est comme *ascmotif? Donc, ça va correspondre, par exemple whereverasc,.
Sopalajo de Arrierez

2
@SopalajodeArrierez Non, cela ne correspond pas à tous les groupes de caractères mais à tous les caractères, par exemple xrar.
Hauke ​​Laging

5

Vous pouvez également demander grepà rechercher votre chaîne en partant d'une limite de mot. A .est l'une de ces limites.

$ ls -R | grep '\brar$'

Exemple

Disons que j'ai cet exemple de données.

$ ls -1
afile.rar
xrar
UFAIZLV2R7.part1.rar.part
UFAIZLV2R7.part2.rar.part

Cette commande ne trouverait que le fichier avec l' .rarextension.

$ ls -R | grep '\brar$'
afile.rar

Comment ça marche?

Le métacaractère \best une ancre comme le caret et le signe dollar. Il correspond à une position appelée "limite de mot". Ce match est de longueur zéro.

Situations où cela ne fonctionnera pas

Si vous avez des fichiers nommés, blah-rarceux-ci seront également détectés.

$ ls -R | grep '\brar$'
afile-rar
afile.rar

En effet, les caractères autres que les caractères alphanumériques sont généralement considérés comme des caractères limites et passeraient donc au-delà de cette approche.


Il semble que ce soit la même chose à première vue, mais c'est en fait légèrement différent. Merci, @slm. Est-ce que ça me dérange si j'utilise des guillemets doubles "au lieu de simples guillemets?
Sopalajo de Arrierez

1
@SopalajodeArrierez - Nope fonctionne dans les deux sens. Cela trouvera tous les fichiers pouvant être nommés en commençant par w / .rar. Mais ce ne sera pas un problème avec l'utilisation de ls -R. Seulement si vous utilisez par hasard ls -Ra.
slm

L'un de vous voudrait-il expliquer cette légère différence au public?
Hauke ​​Laging

@HaukeLaging Le -Ppassage à grepdans mon exemple. Cela déclenche une interprétation PCRE de l'argument.
slm

1
@SopalajodeArrierez - si un fichier contient un caractère de nouvelle ligne ( \n) qui est un caractère légal. Le ls -1Rforcera les fichiers à être affichés dans une seule colonne indépendamment.
slm

0

Il suffit de faire:

ls -1R -I"?" -I"??" -I"???" -I"*[!.][!r][!a][!r]"

Tu n'as pas besoin grepdu tout.

NOTE: Ce qui précède fonctionne ... sauf que ça reste au moins afile-rar et je ne comprends pas pourquoi. Je vais le laisser ici, mais je n'en suis pas fier. En tout cas, comme d'autres l'ont dit:

find . '*.rar'

Cela n'a pas bloqué les fichiers nommés xrarou afile-rar.
slm

Je reçois toujours les autres fichiers dans la sortie.
slm

@slm Quels autres fichiers? Je pense que c'est peut-être parce qu'ils sont trop courts. Je viens de le remarquer moi-même. J'ai corrigé ça aussi.
mikeserv

Les fichiers afile-raret xrarsont toujours inclus dans la sortie. Aucun changement avec vos derniers mods non plus. Problème Pesky non? C'est amusant d'essayer de le résoudre sans les méthodes habituelles 8-)
slm

@slm Oui, c'est pourquoi je viens ici. Je ne comprends pas pourquoi ça -dashpasse. La xrarchose que je pourrais gérer, mais pas le -dash.je ne comprends pas le-dash.
mikeserv

0

Utilisez des guillemets simples pour que $ fonctionne comme fin de ligne. Si vous voulez aussi grep avec une variable, utilisez la combinaison de guillemets simples et doubles comme ci-dessous:

grep "$var"'$'

Mon post précédent a été supprimé en disant qu'il est en double. Laissez-moi vous expliquer en quoi c'est différent.

Les autres publications mentionnent soit l'utilisation complète de doubles guillemets "", soit l'utilisation complète de simples guillemets ''. Ils ont tous deux leurs propres limites. La suite l'explique.

Le problème avec tous les guillemets est le suivant: grep "pattern$"donne l'erreur suivante:Illegal variable name.

Et utiliser tous les guillemets simples fonctionne, mais si vous souhaitez une substitution de variable, tous les guillemets simples ne fonctionneront pas . Par exemple:

Si j'ai une chaîne A_BOOK, y compris d'autres chaînes dans un fichier FILE.

$ cat FILE
A_BOOK
B_BOOK_NOT_LAST
C_BOOK

Si je mets le livre à une variable BK

set BK = BOOK

Si je grep avec toutes les guillemets doubles, j'obtiens le message d'erreur suivant grep "${BK}$" FILE*:: 1er $ pour substitution de variable, 2e pour fin de modèle ( nom de variable illégal ).

Si je grep avec tous les guillemets simples, la substitution de variable ne se produit pas. grep '${BK}$' FILEne renvoie rien

Si j'utilise une combinaison de guillemets simples et doubles, j'obtiens ce que j'attends. Les guillemets doubles pour la substitution de variables et les guillemets simples pour la fin du modèle.

$ grep "${BK}"'$'  # << gives expected output
A_BOOK
C_BOOK

On dirait que vous utilisez csh. La "foo$"syntaxe fonctionne bien sur sh et sa famille.
Olorin

Oui Olorin. J'utilise tcsh. Merci de l'avoir signalé.
user274900 le

0

Si après avoir suivi ce qui précède et que rien ne fonctionne, cela peut être dû à des fins de ligne. Pour réparer, faites: dos2unix pr0n.txtet greprecommencez.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.