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
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țiaquotemeta
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
\/
\\\/\/\/\\\\/
, 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.