grep "^$1" fonctionne en quelque sorte, mais comment puis-je échapper "$1" donc grep ninterprète aucun des caractères spécialement?

Ou y a-t-il une meilleure façon?

Modifier: Je ne veux pas rechercher "^$1" mais une chaîne fixe insérée dynamiquement qui ne devrait être mis en correspondance sil « est au début dune ligne. Cest ce que je voulais dire par $1.

Commentaires

  • Avez-vous essayé dutiliser des guillemets simples au lieu de guillemets doubles, par exemple grep '^$1'? Ou ‘ ne voulez-vous pas dire que vous voulez éviter que $1 ne soit développé par le shell?
  • @mnille Je ne ‘ Je ne veux pas rechercher ‘ ^ $ 1 ‘ mais pour un inséré dynamiquement chaîne fixe qui ne doit être mise en correspondance que si elle ‘ est au début dune ligne. Cest ‘ que je voulais dire par $ 1.
  • Vous pouvez le faire avec grep mais vous ‘ Je devrai dabord échapper tout caractère spécial de votre chaîne, par exemple printf %s ^;printf %s "$1" | sed 's/[][\.*^$]/\\&/g'; } | grep -f- infile
  • @don_crissti que ‘ est meilleur que certaines des autres réponses. Voulez-vous en faire une?
  • @roaima – Je sais mais il y a déjà ‘ un tas de réponses ici et ceci (en échappant aux caractères spéciaux à lintérieur de vars) quelque chose que je (et quelques autres utilisateurs ici) martèle à la maison depuis un certain temps … Vous pouvez toujours lajouter à votre réponse si vous le souhaitez et je ‘ supprimerai le commenter ici (don ‘ t oublier dajouter laccolade de début manquante).

Réponse

Je ne peux « pas penser à un moyen de le faire en utilisant grep; ^ fait lui-même partie dun expression régulière, donc son utilisation nécessite une interprétation des expressions régulières. Cest trivial dutiliser la correspondance de sous-chaînes dans awk, perl ou autre:

awk -v search="$1" "substr($0, 1, length(search)) == search { print }" 

Pour gérer les chaînes de recherche contenant \, vous pouvez utiliser la même astuce que dans Réponse de 123 « :

search="$1" awk "substr($0, 1, length(ENVIRON["search"])) == ENVIRON["search"] { print }" 

Commentaires

  • Cela na ‘ t fonctionner pour des chaînes telles comme \/
  • @ 123 en effet, jai ‘ ajouté une variante pour gérer cela.
  • Échouera toujours pour les chaînes compliquées telles que \\\/\/\/\\\\/ qui est considérée comme \\///\\/ dans le programme. Pour autant que je sache, il ny a aucun moyen déchapper correctement aux contre-obliques dans awk, à moins que vous ne sachiez combien seront utilisées à lavance.
  • @ 123 merci, je ‘ Jai adapté votre astuce pour parcourir lenvironnement pour éviter le traitement déchappement.
  • Jaime toujours cette solution. Efficace (awk + pas de temps perdu à chercher), le démarrage rapide (awk + aucun processus supplémentaire nécessaire pour configurer létat) utilise des outils standard et est assez concis. Toutes les autres réponses en manquent au moins certaines. (Lefficacité est un point fort ici car grep est connu pour sa vitesse inégalée.)

Réponse

Si seulement vous besoin de vérifier si une correspondance est trouvée ou non, couper toutes les lignes dentrée à la longueur du préfixe souhaité ($1) puis utiliser grep à motif fixe:

if cut -c 1-"${#1}" | grep -qF "$1"; then echo "found" else echo "not found" fi 

Il est également facile dobtenir le nombre de lignes correspondantes:

cut -c 1-"${#1}" | grep -cF "$1" 

Ou les numéros de ligne de toutes les lignes correspondantes (les numéros de ligne commencent à 1):

cut -c 1-"${#1}" | grep -nF "$1" | cut -d : -f 1 

Vous pouvez donner les numéros de ligne à head et tail pour obtenir le texte intégral des lignes correspondantes, mais à ce stade, il est plus facile daccéder simplement à un langage de script moderne comme Python ou Ruby.

(Les exemples ci-dessus supposent Posix grep et cut. Ils supposent que le fichier à rechercher provient dune entrée standard, mais peut facilement être adapté pour prendre un nom de fichier à la place.)

Edit: Vous devez également vous assurer que le motif ( $1) nest pas une chaîne de longueur nulle. Sinon, cut ne parvient pas à dire values may not include zero. De plus, si vous utilisez Bash, utilisez set -o pipefail pour intercepter les sorties derreur par cut.

Réponse

Une manière dutiliser perl qui respectera les contre-obliques

v="$1" perl -ne "print if index($_, $ENV{"v"} )==0" file 

Ceci définit la variable denvironnement v pour le commande, puis imprime si lindex de la variable est 0, cest-à-dire le début de la ligne.

Vous pouvez également faire la même chose dans awk

v="$1" awk "index($0, ENVIRON["v"])==1" file 

Answer

Voici une option tout-bash, non pas que je recommande bash pour le traitement de texte, mais cela fonctionne.

#!/usr/bin/env bash # searches for $1 at the beginning of the line of its input len=${#1} while IFS= read -r line do [[ "${line:0:len}" = "$1" ]] && printf "%s\n" "$line" done 

Le script calcule la longueur len du paramètre saisi $ 1, puis utilise le développement des paramètres sur chaque ligne pour voir si les premiers caractères len correspondent à $ 1. Si tel est le cas, il imprime la ligne.

Réponse

Si votre $1 est de lASCII pur et votre grep a loption -P (pour activer PCRE), vous pouvez le faire:

 #!/bin/bash line_start="$1" line_start_raw=$(printf "%s" "$line_start" | od -v -t x1 -An) line_start_hex=$(printf "\\x%s" $line_start_raw) grep -P "^$line_start_hex"  

Lidée ici est que grep -P autorise les expressions régulières avec \xXX pour spécifier des caractères littéraux, où XX est la valeur ASCII hexadécimale de ce caractère. Le caractère er correspond littéralement, même sil sagit dun caractère regex spécial.

od est utilisé pour convertir le début de ligne attendu en une liste de valeurs hexadécimales, qui sont ensuite enchaînés, chacun préfixé par \x par printf. ^ est alors ajoutée au début de cette chaîne pour créer lexpression régulière requise.


Si votre $1 est unicode, alors cela devient un peu plus difficile, car il ny a pas de correspondance 1: 1 entre les caractères et les octets hexadécimaux en sortie de od.

Réponse

Si votre grep a loption -P, ce qui signifie PCRE , vous pouvez faire ceci:

grep -P "^\Q$1\E" 

Reportez-vous à cette question , et consultez le document PCRE pour plus de détails si vous le souhaitez.

Réponse

En tant que filtre:

perl -ne "BEGIN {$pat = shift} print if /^\Q$pat/" search-pattern 

Exécuter sur un ou plusieurs fichiers:

perl -ne "BEGIN {$pat = shift} print if /^\Q$pat/" search-pattern file.. 

La section « Citations de métacaractères » de la documentation de perlre explique:

Citations métacaractères

Métacaractères antislashés en P erl sont alphanumériques, tels que \b, \w, \n. Contrairement à d’autres langages d’expressions régulières, il n’existe pas de symboles antislashés qui ne sont pas alphanumériques. Donc tout ce qui ressemble à \\, \(, \), \[, \], \{ ou \} est toujours interprété comme un caractère littéral, pas un métacaractère. Cela était autrefois utilisé dans un idiome courant pour désactiver ou citer les significations spéciales des métacaractères dexpression régulière dans une chaîne que vous souhaitez utiliser pour un modèle. Citez simplement tous les caractères autres que « mots »:

 $pattern =~ s/(\W)/\\$1/g; 

(Si use locale est défini, cela dépend de les paramètres régionaux actuels.) Aujourdhui, il est plus courant dutiliser la fonction quotemeta ou la séquence déchappement de méta-guillemets \Q pour désactiver les significations spéciales de tous les métacaractères comme ceci:

 /$unquoted\Q$quoted\E$unquoted/ 

Attention, si vous mettez des contre-obliques littérales (celles qui ne sont pas dans des variables interpolées) entre \Q et \E, linterpolation de la barre oblique inverse entre guillemets peut conduire à des résultats confus. Si vous avez besoin dutiliser des contre-obliques littérales dans \Q...\E, consultez « Détails effrayants de lanalyse des constructions entre guillemets » dans Perlop .

quotemeta et \Q sont décrits en détail dans quotemeta .

Réponse

Sil y a un caractère que vous ne « t utiliser, vous pouvez lutiliser pour marquer le début de la ligne. Par exemple, $"\a" (ASCII 007). Cest moche mais cela fonctionnera:

{ echo "this is a line to match"; echo "but this is not"; } >file.txt stuffing=$"\a" # Guaranteed never to appear in your source text required="this" # What we want to match that beginning of a line match=$(sed "s/^/$stuffing/" file.txt | grep -F "$stuffing$required" | sed "s/^$stuffing//") if [[ -n "$match" ]] then echo "Yay. We have a match: $match" fi 

Si vous navez pas besoin de la ou des lignes correspondantes, vous pouvez supprimer le sed et utiliser grep -qF. Mais cest beaucoup plus facile avec awk (ou perl) …

Réponse

Lorsque vous voulez regarder dans un fichier sans boucle, vous pouvez utiliser:
Couper le fichier avec la longueur de la recherche chaîne

Recherchez des chaînes fixes et des numéros de ligne de retour

 grep -Fn "$1" <(cut -c1-${#1} < file) 

Utilisez les numéros de ligne pour quelque chose comme sed -n "3p;11p" file

 sed -n "$(grep -Fn "$1" <(cut -c1-${#1} < file) | sed "s/:.*/p;/" | tr -d "\n")" file 

Lorsque vous souhaitez supprimer ces lignes, utilisez

 sed "$(grep -Fn "$1" <(cut -c1-${#1} < file) | sed "s/:.*/d;/" | tr -d "\n")" file 

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *