grep "^$1" funziona, ma come faccio a scappare "$1" quindi grep non interpreta in modo speciale nessun carattere?

O esiste un modo migliore?

Modifica: Non” voglio cercare "^$1" ma una stringa fissa inserita dinamicamente che dovrebbe essere trovato se si trova allinizio di una riga. Questo è ciò che intendevo con $1.

Commenti

  • Hai provato a utilizzare virgolette singole invece di virgolette doppie, ad es grep '^$1'? Oppure ‘ intendi impedire che $1 venga espanso dalla shell?
  • @mnille Non ‘ voglio cercare ‘ ^ $ 1 ‘ ma un elemento inserito dinamicamente stringa fissa che deve essere trovata solo se ‘ è allinizio di una riga. Questo è ‘ ciò che intendevo con $ 1.
  • Puoi farlo anche con grep ma ‘ dovrà prima eseguire lescape di qualsiasi carattere speciale nella stringa, ad esempio printf %s ^;printf %s "$1" | sed 's/[][\.*^$]/\\&/g'; } | grep -f- infile
  • @don_crissti che ‘ è migliore di alcune delle altre risposte. Ti va di crearne una?
  • @roaima – Lo so ma ‘ ci sono già un mucchio di risposte qui e questo (sfuggendo ai caratteri speciali allinterno di vars) è qualcosa che io (e un paio di altri utenti qui) sto martellando a casa per un bel po di tempo … Puoi sempre aggiungerlo alla tua risposta se lo desideri e io ‘ rimuoverò il commenta qui (don ‘ t dimenticare di aggiungere la parentesi graffa iniziale mancante).

Rispondi

Non riesco “a pensare a un modo per farlo utilizzando grep; ^ stesso fa parte di un espressione regolare, quindi il suo utilizzo richiede linterpretazione di espressioni regolari. È banale usare la corrispondenza della sottostringa in awk, perl o qualsiasi altra cosa:

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

Per gestire le stringhe di ricerca contenenti \, puoi utilizzare lo stesso trucco di 123 “risposta :

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

Commenti

  • Questo ‘ non funzionerà per stringhe come poiché \/
  • @ 123 in effetti, ‘ ho aggiunto una variante per gestirlo.
  • continuerà a fallire per stringhe complicate come \\\/\/\/\\\\/ che è visto come \\///\\/ nel programma. Per quanto ne so, non cè modo di sfuggire correttamente alle barre rovesciate in awk, a meno che tu non sappia quante saranno usate in anticipo.
  • @ 123 grazie, I ‘ ho adattato il tuo trucco di attraversare lambiente per evitare lelaborazione di fuga.
  • Questa soluzione mi piace ancora di più. Efficiente (awk + nessuna perdita di tempo a guardarsi intorno), avvio rapido (awk + nessun processo aggiuntivo necessario per impostare lo stato) utilizza strumenti standard ed è abbastanza conciso. Tutte le altre risposte mancano almeno di alcune di queste. (Lefficienza è un punto di forza qui perché grep è noto per la sua velocità senza pari.)

Rispondi

Se solo è necessario verificare se viene trovata o meno una corrispondenza, tagliare tutte le righe di input alla lunghezza del prefisso desiderato ($1) e quindi utilizzare grep a schema fisso:

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

È anche facile ottenere il conteggio delle righe corrispondenti:

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

O i numeri di riga di tutte le righe corrispondenti (i numeri di riga iniziano da 1):

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

Potresti fornire i numeri di riga a head e tail per ottenere il testo completo delle righe corrispondenti, ma a quel punto è più semplice raggiungere un linguaggio di scripting moderno come Python o Ruby.

(Gli esempi precedenti assumono Posix grep e cut. Presumono che il file da cercare provenga dallo standard input, ma può essere facilmente adattato per prendere un nome di file.)

Modifica: dovresti anche assicurarti che il pattern ( $1) non è una stringa di lunghezza zero. In caso contrario, cut non riesce a pronunciare values may not include zero. Inoltre, se si utilizza Bash, utilizzare set -o pipefail per rilevare le uscite di errore da cut.

Risposta

Un modo di utilizzare perl che rispetterà i backslash

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

Questo imposta la variabile dambiente v per il comando, quindi stampa se lindice della variabile è 0, ovvero linizio della riga.

Puoi anche fare lo stesso in awk

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

Answer

Questa è unopzione all-bash, non che io raccomandi bash per lelaborazione del testo, ma funziona.

#!/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 

Lo script calcola la lunghezza len del parametro immesso $ 1, utilizza lespansione del parametro su ciascuna riga per verificare se i primi len caratteri corrispondono a $ 1. In tal caso, stampa la riga.

Risposta

Se il tuo $1 è puro ASCII e il tuo grep dispone dellopzione -P (per abilitare PCRE), puoi farlo:

 #!/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"  

Lidea qui è che grep -P consente espressioni regolari con \xXX per specificare caratteri letterali, dove XX è il valore ASCII esadecimale di quel carattere. Il carattere er è abbinato letteralmente, anche se è altrimenti un carattere regex speciale.

od viene utilizzato per convertire linizio della riga previsto in un elenco di valori esadecimali, che vengono quindi messi insieme, ciascuno con il prefisso \x da printf. ^ viene quindi anteposto a questa stringa per creare la regex richiesta.


Se $1 è unicode, allora questo diventa un po più difficile, perché non cè una corrispondenza 1: 1 tra caratteri e byte esadecimali come output di od.

Risposta

Se il tuo grep ha lopzione -P, che significa PCRE , puoi farlo:

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

Fai riferimento a questa domanda , e, se lo desideri, consulta il documento PCRE per i dettagli.

Rispondi

Come filtro:

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

Esegui su uno o più file:

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

La sezione “Quoting metacharacters” della documentazione perlre spiega:

Citando metacaratteri

Metacaratteri con barra rovesciata in P erl sono alfanumerici, ad esempio \b, \w, \n. A differenza di altri linguaggi di espressioni regolari, non sono presenti simboli con barra rovesciata che non siano alfanumerici. Quindi tutto ciò che assomiglia a \\, \(, \), \[, \], \{ o \} viene sempre interpretato come un carattere letterale, non un metacarattere. Questo veniva usato una volta in un linguaggio comune per disabilitare o citare i significati speciali dei metacaratteri delle espressioni regolari in una stringa che si desidera utilizzare per un modello. Cita semplicemente tutti i caratteri non “parola”:

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

(se use locale è impostato, questo dipende da la locale corrente.) Oggi è più comune utilizzare la funzione quotemeta o la sequenza di escape metaquotante \Q per disabilitare i significati speciali di tutti i metacaratteri in questo modo:

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

Fai attenzione che se inserisci barre rovesciate letterali (quelle non allinterno di variabili interpolate) tra \Q e \E, linterpolazione con barra rovesciata doppia virgoletta può portare a risultati confusi. Se devi utilizzare barre rovesciate letterali allinterno di \Q...\E, consulta “Dettagli cruenti dellanalisi di costrutti quotati” in perlop .

quotemeta e \Q sono completamente descritti in quotemeta .

Risposta

Se cè un carattere che indossi “Da usare, potresti usarlo per contrassegnare linizio della riga. Ad esempio, $"\a" (ASCII 007). È brutto ma funzionerà:

{ 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 

Se non hai bisogno delle linee corrispondenti, puoi rilasciare sed e utilizzare grep -qF. Ma è molto più facile con awk (o perl) …

Risposta

Quando vuoi cercare in un file senza loop puoi usare:
Taglia il file con la lunghezza della ricerca stringa

Cerca stringhe fisse e numeri di riga di ritorno

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

Utilizza i numeri di riga per qualcosa come sed -n "3p;11p" file

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

Quando desideri eliminare queste righe, utilizza

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

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *