grep "^$1" fel de lucrări, dar cum scap "$1" deci grep nu interpretează special caractere din acesta?

Sau există un mod mai bun?

Edit: Nu vreau să caut "^$1" ci un șir fix inserat dinamic care ar trebui doar se potrivește dacă este „la începutul unei linii. Asta este ceea ce am vrut să spun prin $1.

Comentarii

  • Ați încercat să utilizați ghilimele simple în loc de ghilimele duble, de ex grep '^$1'? Sau nu ‘ vrei să spui că vrei să împiedici extinderea $1 de către shell?
  • @mnille Nu ‘ nu vreau să caut ‘ ^ $ 1 ‘, ci pentru o inserare dinamică șir fix care ar trebui să se potrivească numai dacă ‘ este la începutul unei linii. ‘ este ceea ce am vrut să spun prin $ 1.
  • Puteți face acest lucru și cu grep, dar dvs. ‘ va trebui mai întâi să scape de orice caracter special din șirul dvs. de ex. printf %s ^;printf %s "$1" | sed 's/[][\.*^$]/\\&/g'; } | grep -f- infile
  • @don_crissti că ‘ este mai bun decât unele dintre celelalte răspunsuri. Doriți să-l faceți unul?
  • @roaima – Știu, dar există deja ‘ aici o grămadă de răspunsuri și acest lucru (scăpând de caracterele speciale din vars) este ceva pe care eu (și câțiva alți utilizatori de aici) l-am acaparat de ceva timp … Puteți să-l adăugați întotdeauna la răspunsul dvs. dacă doriți și ‘ voi elimina comentează aici (nu ‘ nu uitați să adăugați lipsa paranteză principală).

Răspundeți

Nu pot să mă gândesc la o modalitate de a face acest lucru folosind grep; ^ în sine face parte dintr-un expresia regulată, deci utilizarea acesteia necesită interpretarea expresiilor regulate. Este banal folosind potrivirea subșirului în awk, perl sau orice altceva:

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

Pentru a gestiona șirurile de căutare care conțin \, puteți utiliza același truc ca în Răspunsul 123 „:

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

Comentarii

  • Aceasta nu a funcționat pentru ‘ ca \/
  • @ 123 într-adevăr, am ‘ am adăugat o variantă pentru a gestiona acest lucru.
  • Va eșua în continuare pentru șirurile complicate, cum ar fi \\\/\/\/\\\\/, care este văzut ca \\///\\/ în program. Din câte știu, nu există nicio modalitate de a scăpa corect de backslashes în awk, cu excepția cazului în care știți câte vor fi utilizate în prealabil.
  • @ 123 mulțumesc, eu ‘ ți-am adaptat trucul de a trece prin mediu pentru a evita procesarea evadării.
  • Îmi place în continuare această soluție cel mai bine. Eficient (awk + fără timp pierdut privind în jur), pornire rapidă (awk + fără procese suplimentare necesare pentru starea de configurare) utilizează instrumente standard și este destul de concis. Toate celelalte răspunsuri lipsesc cel puțin unele dintre acestea. (Eficiența este un punct forte aici, deoarece grep este cunoscut pentru viteza de neegalat.)

Răspuns

Dacă numai trebuie să verificați dacă se găsește sau nu o potrivire, tăiați toate liniile de intrare la lungimea prefixului dorit ($1) și apoi utilizați grep cu model fix:

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

De asemenea, este ușor să obțineți numărul de linii potrivite:

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

Sau numerele de linie ale toate liniile potrivite (numerele de linie încep de la 1):

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

Puteți alimenta numerele de linie către head și tail pentru a obține textul complet al liniilor potrivite, dar în acel moment este mai ușor să ajungeți doar la un limbaj de script modern, cum ar fi Python sau Ruby.

(Exemplele de mai sus presupun Posix grep și cut. Acestea presupun că fișierul de căutat provine de la intrarea standard, dar poate fi ușor adaptat pentru a lua în schimb un nume de fișier.)

Edit: Ar trebui să vă asigurați, de asemenea, că modelul ( $1) nu este un șir de lungime zero. În caz contrar, cut nu reușește să spună values may not include zero. De asemenea, dacă utilizați Bash, utilizați set -o pipefail pentru a prinde ieșirile de erori de cut.

Răspuns

O modalitate de a utiliza perl care va respecta barele oblice

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

Aceasta setează variabila de mediu v pentru , apoi imprimă dacă indexul variabilei este 0, adică începutul liniei.

Puteți face, de asemenea, identic în awk

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

Răspuns

Aici este o opțiune complet bash, nu că recomand recomandarea bash pentru procesarea textului, dar funcționează.

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

Scriptul calculează lungimea len al parametrului introdus $ 1, apoi folosește extinderea parametrilor pe fiecare linie pentru a vedea dacă primele caractere len se potrivesc cu $ 1. Dacă da, acesta imprimă linia.

Răspuns

Dacă $1 este ASCII pur și grep are opțiunea -P (pentru a activa PCRE), puteți face acest lucru:

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

Ideea este că grep -P permite expresii regulate cu \xXX pentru a specifica caractere literale, unde XX este valoarea ASCII hexagonală a acelui caracter. er se potrivește literalmente, chiar dacă este altfel un caracter special regex.

od este utilizat pentru a converti începutul liniei așteptate într-o listă de valori hex, care sunt apoi strânse împreună, fiecare prefixat cu \x de printf. ^ este apoi precedat de acest șir pentru a construi regexul necesar.


Dacă $1 este unicode, atunci acest lucru devine destul de greu, deoarece nu există o corespondență 1: 1 a caracterelor cu octeți hexagonali ca ieșire de od.

Răspuns

Dacă grep-ul dvs. are opțiunea -P, ceea ce înseamnă PCRE , puteți face acest lucru:

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

Consultați această întrebare , și consultați doc PCRE pentru detalii, dacă doriți.

Răspundeți

Ca filtru:

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

Rulați pe unul sau mai multe fișiere:

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

Secțiunea „Citat metacaractere” din documentația perlre explică:

Citat metacaractere

Metacaractere inversate în P erl sunt alfanumerice, cum ar fi \b, \w, \n. Spre deosebire de alte limbi de expresie obișnuită, nu există simboluri inversate care să nu fie alfanumerice. Deci, orice arata ca \\, \(, \), \[, \], \{ sau \} este întotdeauna interpretat ca un caracter literal, nu un metacaracter. Acest lucru a fost folosit odată într-un idiom obișnuit pentru a dezactiva sau a cita semnificațiile speciale ale metacaracterelor de expresie regulată într-un șir pe care doriți să îl utilizați pentru un model. Pur și simplu citați toate caracterele care nu sunt „cuvânt”:

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

(Dacă este setat use locale, atunci acest lucru depinde de locația curentă.) Astăzi este mai frecvent să folosiți funcția quotemeta sau secvența de evadare \Q metacotare pentru a dezactiva semnificațiile speciale ale tuturor metacaracterelor așa:

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

Atenție la faptul că, dacă puneți backslash-uri literal (cele care nu se află în variabile interpolate) între \Q \E, interpolare inversă dublă-cotă poate duce la rezultate confuze. Dacă aveți nevoie să folosiți bare oblice înapoi literal în \Q...\E, consultați „Detalii Gory despre analizarea constructelor citate” în perlop .

quotemeta și \Q sunt complet descrise în quotemeta .

Răspuns

Dacă există un personaj pe care nu îl dai „nu folosiți, puteți folosi acest lucru pentru a marca începutul liniei. De exemplu, $"\a" (ASCII 007). Este urât, dar va funcționa:

{ 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 

Dacă nu aveți nevoie de rândurile potrivite, puteți renunța la sed și utilizați grep -qF. Dar este „mult mai ușor cu awk (sau perl) …

Răspuns

Când doriți să căutați într-un fișier fără buclă puteți utiliza:
Tăiați fișierul cu lungimea căutării șir

Căutați șiruri fixe și întoarceți numerele de linie

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

Folosiți numerele de linie pentru ceva de genul sed -n "3p;11p" file

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

Când doriți să ștergeți aceste linii, utilizați

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

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *