grep "^$1" amolyan művek, de hogyan menekülhetek "$1" tehát a grep nem értelmezi külön a benne szereplő karaktereket?

Vagy van ennél jobb módszer?

Szerkesztés: Nem a "^$1" -et akarom keresni, hanem egy dinamikusan beillesztett fix karakterláncot, amely csak illeszkedjen, ha egy sor elején van. Ezt értettem a $1 alatt.

Megjegyzések

  • Megpróbáltál egyetlen idézetet használni kettős idézőjel helyett, pl grep '^$1'? Vagy nem ‘ t arra gondoltál, hogy meg akarod akadályozni, hogy a $1 kiterjedjen a héj?
  • @mnille Nem ‘ nem akarok ‘ ^ $ 1 ‘ keresni, hanem dinamikusan beilleszteni fix karakterlánc, amely csak akkor illeszthető össze, ha ‘ s a sor elején. ‘ ezt értettem az $ 1 alatt.
  • Megteheti a grep kapcsolattal is, de ‘ Először el kell menekülnöd a karaktered bármelyik speciális karakterétől, pl. printf %s ^;printf %s "$1" | sed 's/[][\.*^$]/\\&/g'; } | grep -f- infile
  • @don_crissti, amely ‘ jobb, mint a többi válasz. Érdekel, hogy ilyen legyen?
  • @roaima – tudom, de ‘ itt már egy csomó válasz van, és ez (elkerülve a vars-okon belüli különleges karaktereket) amit én (és még néhány más itteni felhasználó) jó ideje kalapálok hazafelé … Mindig hozzáteheti a válaszához, ha akarja, és ‘ eltávolítom a írjon ide (ne ‘ ne felejtse el hozzáadni a hiányzó zárójelet).

Válasz

Nem tudok elképzelni egy módot ennek megvalósítására a grep; önmagában a ^ használatával A reguláris kifejezés használatához a reguláris kifejezések értelmezése szükséges. Ez triviális a awk, perl vagy bármi másban:

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

Az \ -t tartalmazó keresési karakterláncok kezeléséhez ugyanazt a trükköt használhatja, mint a 123-as válasz :

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

Megjegyzések

  • Ez ‘ nem fog működni az ilyen karakterláncoknál mivel \/
  • @ 123 valóban, én ‘ hozzáadtam egy változatot ennek kezelésére.
  • Továbbra is meg fog bukni olyan bonyolult karakterláncok esetében, mint például a \\\/\/\/\\\\/, amelyek \\///\\/ néven láthatók a programban. Tudomásom szerint nincs mód az awk visszavágások megfelelő elkerülésére, hacsak nem tudod, mennyit fognak felhasználni előzetesen.
  • @ 123 köszönöm, I ‘ a környezetben való átjutás trükkjét úgy alakítottuk át, hogy elkerüljük a menekülési folyamatokat.
  • Még mindig ez a megoldás tetszik a legjobban. A hatékony (awk + nincs vesztegetett idő körülnézéssel), a gyors indítás (awk + nincs szükség további folyamatokra az állapot beállításához) szabványos eszközöket használ, és elég tömör. Az összes többi válaszból hiányzik ezek közül legalább néhány. (A hatékonyság itt erős pont, mivel a grep a páratlan sebességről ismert.)

Válasz

Ha csak ellenőrizni kell, hogy található-e egyezés vagy sem, az összes beviteli sort vágja le a kívánt előtag hosszára ($1), majd használja a fix mintás grep-t:

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

Könnyű megszerezni az egyező sorok számát is:

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

Vagy a minden egyező sor (a sorszámok 1-től kezdődnek):

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

A sorszámokat a head és tail az egyező sorok teljes szövegének megszerzéséhez, de ekkor könnyebb elérni egy olyan modern szkriptnyelvet, mint a Python vagy a Ruby.

(A fenti példák feltételezik, hogy a Posix grep és cut. Feltételezik, hogy a keresendő fájl szabványos bemenetről származik, de könnyen adaptálható fájlnév felvételére.)

Szerkesztés: Gondoskodnia kell arról is, hogy a minta ( $1) nem nulla hosszúságú karakterlánc. Ellenkező esetben cut nem sikerül kimondani a values may not include zero szót. Ezenkívül a Bash használatakor használja a set -o pipefail elemet a hibakibocsátások elkapásához cut szerint.

Válasz

A perl használatával a visszavágásokat tiszteletben tartva

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

Ez beállítja a v környezeti változót parancsot, majd kinyomtatja, ha a változó indexe 0, azaz a sor eleje.

Ugyanezt megteheti az awk

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

Válasz

fájlban is

Itt egy all-bash opció, nem az, hogy a bash-t javaslom a szövegfeldolgozáshoz, de működik.

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

A szkript kiszámítja a hosszt A beírt $ 1 paraméter len, majd az egyes sorok paraméterbővítésével megnézi, hogy az első len karakterek megegyeznek-e a dollárral. Ha igen, akkor kinyomtatja a sort.

Válasz

Ha a $1 fájlja tiszta ASCII, és a A grep rendelkezik a -P opcióval (a PCRE engedélyezéséhez), ezt megteheti:

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

Az ötlet az, hogy grep -P lehetővé teszi a reguláris kifejezéseket \xXX szó szerinti karakterek megadásához, ahol XX az adott karakter hex ASCII értéke. Az er szó szerint illeszkedik, még akkor is, ha ez egyébként egy speciális regex karakter.

od arra szolgál, hogy a várt sorkezdet hexa értékek listájává konvertálja, amelyek ezután összefűzik őket, mindegyiket a \x előtaggal nyomtatja a printf. A ^ ezt a karakterláncot előkészíti a szükséges regex készítéséhez.


Ha a $1 unicode, akkor ez kissé nehezebbé válik, mert a karakterek 1: 1 arányban nem felelnek meg a hex bájtoknak od kimeneteként.

Válasz

Ha a grep a -P opcióval rendelkezik, ami azt jelenti: PCRE , ezt megteheti:

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

Lásd ezt a kérdést , és a részletekért lásd: PCRE doc , ha úgy tetszik.

Válasz

Szűrőként:

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

Futtatás egy vagy több fájlon:

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

A perlre dokumentáció „Metakarakterek idézése” szakasza elmagyarázza:

Idézés metakarakterek

Visszavágott metakarakterek a P-ben Az erl alfanumerikus, például: \b, \w, \n. Néhány más reguláris kifejezés nyelvétől eltérően nincsenek visszavágott szimbólumok, amelyek nem alfanumerikusak. Tehát minden, ami úgy néz ki, mint \\, \(, \), , \], \{ vagy \} szöveget mindig úgy értelmezik szó szerinti karakter, nem metakarakter. Ezt egyszer egy közös szóhasználatban használták a szabályos kifejezés metakaraktereinek speciális jelentéseinek letiltására vagy idézésére egy olyan karaktersorozatban, amelyet a mintához használni kívánt. Egyszerűen idézzen be minden nem „word” karaktert:

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

(Ha a use locale be van állítva, akkor ez az aktuális területi beállítás.) Ma gyakoribb, ha a quotemeta függvényt vagy a \Q metaquoting menekülési szekvenciát használjuk az összes metakarakter speciális jelentésének letiltásához. így:

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

Vigyázzon, hogy ha szó szerinti visszavágásokat (az interpolált változókon kívülieket) \Q és \E, a dupla idézőjeles visszavágó interpoláció zavaros eredményekhez vezethet. Ha szó szerinti visszavonásokat kell használnia a \Q...\E belül, olvassa el a “Az idézett konstrukciók elemzésének részletes adatai” című részt a perlopon .

quotemeta és \Q részletesen leírják az quotemeta .

Válasz

Ha van olyan karakter, amelyet nem ad “ne használja, ezzel jelölheti a sor elejét. Például $"\a" (ASCII 007). Ez csúnya, de működni fog:

{ 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 

Ha nincs szüksége az egyező sor (ok) ra, akkor eldobhatja a záró sed elemet és használhatja a grep -qF. De ez sokkal könnyebb a awk (vagy perl) használatával …

Válasz

Ha hurok nélkül szeretne fájlba nézni, használhatja:
Vágja a fájlt a keresés hosszával karakterlánc

Rögzített karakterláncok és visszatérő sorok keresése

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

Használja a sorszámokat például sed -n "3p;11p" file

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

Ha törölni szeretné ezeket a sorokat, használja a

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

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük