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 $1
.
Kommentit
Vastaa
En voi ajatella tapaa tehdä se käyttämällä grep
; ^
itsessään on osa säännöllinen lauseke, joten sen käyttö edellyttää säännöllisten lausekkeiden tulkintaa. Se on vähäpätöinen, kun käytetään alakoodaushakua awk
, perl
tai mitä tahansa:
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 voinut toimia ’ sellaisilla merkkijonoilla 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 kaavan grep:
if cut -c 1-"${#1}" | grep -qF "$1"; then echo "found" else echo "not found" fi
Vastaavien rivien lukumää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 nähdäksesi, 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 (PCRE: n käyttöön ottamiseksi), 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 muuttamaan odotettu rivin alku heksalukuarvojen luetteloksi, joka sidotaan 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-dokumentaation ”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
-metakoodauspakosarjaa 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 . / p>
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
) …
vastaus
Kun haluat etsiä tiedostoa ilman silmukkaa, voit käyttää sitä:
Leikkaa tiedosto haun pituudella merkkijono
Etsi kiinteitä merkkijonoja ja palaa rivinumeroihin
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
grep '^$1'
? Tai eikö ’ t tarkoittanut, että haluat estää$1
laajentamisen kuoren avulla?grep
, mutta ’ ll täytyy ensin välttää kaikki merkkijonosi merkkijonot, esimprintf %s ^;printf %s "$1" | sed 's/[][\.*^$]/\\&/g'; } | grep -f- infile