Stampa il testo tra due motivi


0

Ho bisogno di:

Stampa il testo tra i motivi "ciao" e "ciao".

I modelli possono essere ripetuti e ci possono essere più occorrenze di hi.. hello.

File sorgente:

hi aa bb cc
dd ee ff
hello xxxxxx
aaaa dddd cccc hi aaa bbb
ccc hello cccc fff

Uscita prevista.

hi aa bb cc
dd ee ff
hello
hi aaa bbb
ccc hello

Ho provato con awke sed -ncomandi mentre mostra tutta la linea tra la prima occorrenza di hie l'ultima occorrenza di hello.


È necessario pubblicare un esempio più ampio di file di input e output previsto, inclusi i blocchi multipli.
Jimmij,

1
Mostra anche come deve essere trattato un file con più hi/ hello(sulla stessa riga e su righe consecutive).
Kusalananda

Risposte:


2

Dal primo ciao al primo ciao che segue.

grep

Utilizzando (GNU) grep e tr:

$ <infile grep -oPz "(?s)hi.*?hello" | tr '\0' '\n'
hi aa bb cc
dd ee ff
hello
hi aaa bbb
ccc hello

Descripttion:

  • <infile File sorgente.
  • grep -oPz Chiama grepa:
    • ( -P) corrisponde a una P CRE (espressione regolare compatibile Perl)
    • ( -o) O olo stampare la parte corrispondente.
    • ( -z) usa un byte z ero (aka NUL e aka \0) come delimitatore di linea.
  • "(?s)Rendi il punto PCRE ( .) corrispondente anche alle nuove righe.
  • hiA partire dalla stringa hi.
  • .*?Abbina tutti i personaggi che seguono (non avidi a causa di ?).
  • hello"Fino a quando la stringa helloè abbinata.
  • | tr '\0' '\n'Convertire i \0byte NUL ( ) (da grep -z) in newline.

sed

GNU sed:

<infile sed 's/hi/\n&/;s/[^\n]*\n//;s/\(hello\).*/\1/;/hi/,/hello/!d'

Oppure, per BSD sed, che non consente \nsul lato destro di s///, è necessario definire una newlinevariabile nl:

$ eval "$(printf "nl='\n'")"

E poi:

<infile sed 's/hi/\'"$nl"'&/;s/[^\n]*\n//;s/\(hello\).*/\1/;/hi/,/hello/!d'

O; se potessi scrivere una nuova riga esplicita:

<infile sed 's/hi/\
&/;s/[^\n]*\n//;s/\(hello\).*/\1/;/hi/,/hello/!d'

Grazie per il tuo tempo e il tuo suggerimento, ho provato con il comando di seguito e ha funzionato, ma ha aggiunto la lettera n prima di ciao, ha anche preso la linea completa del modello di partenza, di seguito è il o / pi ottenuto
user314870

nhi aa bb cc dd ee ff hello aaaa dddd cccc nhi aaa bbb ccc hello
user314870

comando ho provato a compilare sed 's / hi / \ n & /; s / [^ \ n] * \ n //; s / (hello). * / \ 1 /; / hi /, / hello /! d'
user314870

Quindi, hai una BSD sed, che non consente a \nsul lato destro di s///. Utilizzare le versioni BSD. @utente314870
Isaac

Non hai bisogno della trparte. Grep non si sostituisce \na \0causa di -z(provalo!), Sta solo cercando le linee separate da \0anziché invece \n, il che nella maggior parte dei casi consente di guardare l'intero file come una singola riga. I \npersonaggi rimangono intatti, però.
Benjamin W.

0
grep -oPz "(?s)hi.*?hello" fileName

Spiegazione di seguito.

cat tmp

Uscita ->

hi aa bb cc
dd ee ff
hello xxxxxx
aaaa dddd cccc hi aaa bbb
ccc hello cccc fff
00000000000
hi ff 
djd h
sdkf hello
dfj 

Soluzione:

grep -oPz "(?s)hi.*?hello" tmp

Uscita ->

hi aa bb cc
dd ee ff
hello
hi aaa bbb
ccc hello
hi ff 
djd h
sdkf hello

Parametri:

  • -zquesta opzione dice a grep di trattare le nuove righe come normali caratteri di testo e di cercare byte null per separare i record. In un file di testo senza byte null, grep -ztratterà l'intero file come una riga.

  • (?s)attivare PCRE_DOTALL, che significa che '.' trova qualsiasi personaggio o newline.

  • o Stampa solo la parte corrispondente

  • -P Interpreta il pattern come un'espressione regolare compatibile con Perl (PCRE). Questo è altamente sperimentale, in particolare se combinato con l'opzione -z (--null-data) e 'grep -P' può avvisare di funzionalità non implementate.

  • .*?Per una partita non golosa. Inizia a cercare la corrispondenza successiva di hiquando trovi la prima istanza dihello

    Fonte: https://www.gnu.org/software/grep/manual/grep.html


L' -zoutput grep includerà alcuni \0(non newline). Quelli devono essere cambiati.
Isaac,

0

impacciato per le risatine

#!/usr/bin/awk -f
{
    n=split($0, col, FS)
    for(i=1;i<=n;i++){
        (i==n)? sp="" : sp=FS
        if (col[i] ~ /hi/) p=1
        if (p == 1  && col[i] ~ /hello/) h=1
        if (p == 1) printf("%s%s",col[i],sp)
        if (h==1) p=0;h=0
    }
    printf "\n"
}



kapu@jake:$ cat SourceFile
hi aa bb cc
dd ee ff
hello xxxxxx
aaaa dddd cccc hi aaa bbb
ccc hello cccc fff
kapu@jake:$ script.awk SourceFile
hi aa bb cc
dd ee ff
hello
hi aaa bbb
ccc hello
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.