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
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
grep '^$1'
? Tai eikö ’ t tarkoittanut, että haluat estää$1
-kuvakkeen laajentamisen kuoren avulla?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