grep "^$1" eräänlainen teos, mutta miten pääsen "$1" joten grep ei tulkitse mitään merkkejä siinä erikseen?

Vai onko olemassa parempi tapa?

Muokkaa: En halua etsiä hakemistoa "^$1", mutta dynaamisesti lisättyä kiinteää merkkijonoa, jonka pitäisi vain vastaamaan, jos se on rivin alussa. Tarkoitin sitä $1.

Kommentit

  • Yrititkö käyttää yksittäisiä lainauksia kaksoislainausten sijasta, esim grep '^$1'? Tai eikö ’ t tarkoittanut, että haluat estää $1 -kuvakkeen laajentamisen kuoren avulla?
  • @mnille En halua ’ halua etsiä hakusanaa ’ ^ $ 1 ’ mutta dynaamisesti lisättyä kiinteä merkkijono, joka tulisi sovittaa vain, jos se ’ on rivin alussa. Että ’ tarkoitin sitä, mitä tarkoitin $ 1: lla.
  • Voit tehdä sen myös grep -sivulla, mutta sinä ’ ll täytyy ensin välttää kaikki merkkijonosi erikoismerkit, esim. printf %s ^;printf %s "$1" | sed 's/[][\.*^$]/\\&/g'; } | grep -f- infile
  • @don_crissti että ’ on parempi kuin jotkut muut vastaukset. Haluatko tehdä siitä yhden?
  • @roaima – tiedän, mutta ’ on jo joukko vastauksia täällä ja tämä (pakeneminen varsissa olevien erikoismerkkien takia) on jotain, jonka minä (ja muutama muu täällä oleva käyttäjä) on lyönyt kotiin jo jonkin aikaa … Voit aina lisätä sen vastaukseesi, jos haluat, ja minä ’ poistan kommentoi täällä (älä ’ unohda lisätä puuttuva etusulku).

Vastaa

En voi ajatella tapaa tehdä tämä käyttämällä grep; ^ itse on osa säännöllinen lauseke, joten sen käyttö edellyttää säännöllisten lausekkeiden tulkintaa. Se on vähäpätöinen käyttämällä alakoodaushakua awk, perl tai mitä tahansa muuta:

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

Voit käsitellä hakusarjoja, jotka sisältävät \, käyttämällä samaa temppua kuin kohdassa 123: n vastaus :

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

Kommentit

  • Tämä ei voittanut ’ t kuten \/
  • @ 123 todellakin, olen ’ lisännyt muunnoksen sen käsittelemiseksi.
  • Epäonnistuu edelleen monimutkaisissa merkkijonoissa, kuten \\\/\/\/\\\\/, joka nähdään ohjelmassa nimellä \\///\\/. Sikäli kuin olen tietoinen, ei ole mitään keinoa välttää kunnolla vinoviivoja awk: ssä, ellet tiedä, kuinka monta sitä käytetään etukäteen.
  • @ 123 kiitos, I ’ olemme mukauttaneet temppusi käydä läpi ympäristön välttääksesi pakenemisprosessin.
  • Pidän edelleen parhaiten tästä ratkaisusta. Tehokas (awk + aikaa ei hukata ympärilleen katsomiseen), nopea käynnistys (awk + ei lisäprosesseja, joita tarvitaan tilan määrittämiseen) käyttää vakiotyökaluja ja on melko ytimekäs. Kaikista muista vastauksista puuttuu ainakin osa näistä. (Tehokkuus on tässä vahva kohta, koska grep tunnetaan vertaansa vailla olevasta nopeudesta.)

Vastaa

Jos vain täytyy tarkistaa, löytyykö osuma vai ei, leikkaa kaikki syöttörivit halutun etuliitteen pituudelle ($1) ja käytä sitten kiinteän mallin grep:

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

Vastaavien rivien määrän saaminen on myös helppoa:

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

Tai rivien numerot kaikki vastaavat rivit (rivinumero alkaa kohdasta 1):

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

Voit syöttää rivinumeroita head ja tail saadaksesi vastaavien rivien koko tekstin, mutta siinä vaiheessa on helpompi tavoittaa moderni komentosarjakieli, kuten Python tai Ruby.

(Edellä olevissa esimerkeissä oletetaan, että Posix grep ja cut. He olettavat, että haettava tiedosto tulee tavallisesta syötteestä, mutta voidaan helposti mukauttaa ottamaan sen sijaan tiedostonimi.)

Muokkaa: Varmista myös, että kuvio ( $1) ei ole nollapituinen merkkijono. Muuten cut epäonnistuu sanomalla values may not include zero. Jos käytät Bashia, käytä set -o pipefail -näppäintä myös virheiden poistumisten havaitsemiseksi cut.

Vastaa

Tapa, jolla käytetään perl-tiedostoa, joka kunnioittaa paluuviivoja

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

Tämä asettaa ympäristömuuttujan v komento, tulostaa sitten, jos muuttujan indeksi on 0 eli rivin alku.

Voit tehdä samanlaisen myös tiedostossa awk

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

Vastaa

Tässä on all-bash-vaihtoehto, en suosittelen bash-tekstiä tekstinkäsittelyyn, mutta se toimii.

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

Komentosarja laskee pituuden Syötetyn parametrin $ 1 len, sitten käyttää kunkin rivin parametrilaajennusta tarkistaakseen, vastaavatko ensimmäiset len merkit arvoa $ 1. Jos näin on, se tulostaa viivan.

Vastaa

Jos $1 on puhdas ASCII ja grep -kohdassa on -P -vaihtoehto (jotta PCRE voidaan ottaa käyttöön), voit tehdä tämän:

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

Ajatuksena on, että grep -P sallii säännölliset lausekkeet \xXX määrittää kirjaimelliset merkit, joissa XX on kyseisen merkin heksadesimaalinen ASCII-arvo. er täsmää kirjaimellisesti, vaikka se muuten olisikin erityinen regex-merkki.

od käytetään muuntaa odotettu rivin alku heksalukuarvojen luetteloksi, joka neidotaan sitten yhteen, kukin etuliitteellä \x printf: llä. ^ lisätään sitten tämä merkkijono tarvittavan regexin luomiseksi.


Jos $1 on unicode, silloin tästä tulee melko vaikeampaa, koska merkkien vastaavuus heksatavuihin ei ole 1: 1 od.

Vastaus

Jos grepillä on vaihtoehto -P, mikä tarkoittaa PCRE , voit tehdä tämän:

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

Katso tämä kysymys , ja katso lisätietoja PCRE-asiakirjasta , jos haluat.

Vastaa

Suodattimena:

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

Suorita yhdellä tai useammalla tiedostolla:

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

Perlre-asiakirjojen ”Metakohteiden lainaaminen” -osassa selitetään:

Lainaus metahahmot

Taaksepäin leikatut metahahmot P: ssä erl ovat aakkosnumeerisia, kuten \b, \w, \n. Toisin kuin jotkut muut säännöllisen lausekkeen kielet, ei ole taaksepäin viivoitettuja symboleja, jotka eivät ole aakkosnumeerisia. Joten kaikki, mikä näyttää \\, \(, \), \[, \], \{ tai \} tulkitaan aina kirjaimellinen hahmo, ei metahahmo. Tätä käytettiin kerran tavallisessa idiomassa poistaaksesi tai lainaten säännöllisen lausekkeen metamerkkien erityisiä merkityksiä merkkijonossa, jota haluat käyttää kuviossa. Lainaa vain kaikki muut kuin ”sana” -merkit:

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

(Jos use locale on asetettu, tämä riippuu nykyinen aluekohta.) Nykyään on yleisempää käyttää quotemeta -funktiota tai \Q -metakoodaavaa pakosarjaa kaikkien metamerkkien erityiskertojen poistamiseksi käytöstä. näin:

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

Varo, että jos laitat kirjaimelliset taaksepäinviivat (jotka eivät ole interpoloitujen muuttujien sisällä) \Q ja \E, kaksoislainausmerkkiviiva-interpolointi voi johtaa hämmentäviin tuloksiin. Jos sinun on käytettävä kirjaimellisia taaksepäinviivoja \Q...\E -kohdassa, katso ”Lainattujen rakenteiden jäsentämisen yksityiskohdat” perlopissa .

quotemeta ja \Q on kuvattu perusteellisesti osiossa quotemeta .

Vastaa

Jos on jokin merkki, jota et halua ”Älä käytä, voit käyttää sitä merkitsemään rivin alun. Esimerkiksi $"\a" (ASCII 007). Se on ruma, mutta se toimii:

{ 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 

Jos et tarvitse vastaavia viivoja, voit jättää jäljessä olevan sed ja käyttää grep -qF. Mutta se on paljon helpompaa awk (tai perl) kanssa …

vastaus

Kun haluat etsiä tiedostoa ilman silmukkaa, voit käyttää sitä:
Leikkaa tiedosto haun pituudella merkkijono

Etsi kiinteitä merkkijonoja ja paluuviivojen numeroita

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

Käytä rivinumeroita esimerkiksi sed -n "3p;11p" file

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

Kun haluat poistaa nämä rivit, käytä

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

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *