Ich habe eine Textdatei, die so aussieht:

# Query 1:
.
.
.
# Hosts ip-127-0-0-1
.
.
.

# Query 2:
.
.

In meiner Datei befinden sich möglicherweise mehrere Abfragen. Ich möchte die Informationen nur extrahieren, wenn meine IP-Adresse KEIN bestimmter Wert ist.

Zum Beispiel möchte ich hier beginnend mit '# Abfrage 1' bis zu dem Leerzeichen direkt davor erfassen, wo '# Abfrage 2' steht - ich muss dies jedoch NUR tun, wenn Hosts IP NICHT mit IP-127-0-0 übereinstimmt -1. Dies ist keine exakte Übereinstimmung, da an ip-127-0-0-1 anderer Text wie ip-127-0-0-1.notusefultext an das Ende angehängt werden kann

Ich bin offen für die Verwendung von awk, sed oder python, um dieses Problem zu lösen.

0
user3299633 19 Jän. 2019 im 03:53

4 Antworten

Beste Antwort

Dies könnte für Sie funktionieren (GNU sed):

sed -n '/^# Query [0-9]*:/{:a;N;/^\s*$/M!ba;/Hosts.*127-0-0-1/I!p}' file

Verwenden Sie die Option -n von sed, um nur explizit zu drucken. Konzentrieren Sie sich auf eine Zeile, die mit # Query n*: beginnt, wobei n* null oder mehr Ziffern bedeutet (verwenden Sie [^:]*, wenn diese Übereinstimmung zu spezifisch ist). Sammeln Sie die aktuellen und folgenden Zeilen bis (einschließlich) einer leeren Zeile. Testen Sie die Zeilensammlung für die Zeichenfolge 127-0-0-1 und drucken Sie die Sammlung aus, falls sie nicht vorhanden ist. Alle anderen Zeilen werden nicht gedruckt.

N.B. Die Auflistung enthält sowohl die Abfragezeile als auch die Leerzeile. Dies ist möglicherweise nicht der Fall, wenn die letzte Abfrage keine Leerzeile als letzte Zeile der Datei enthält. Dies kann durch eine verbesserte Version sichergestellt werden:

sed -n '/^# Query [0-9]*:/{:a;$!{N;/^\s*$/M!ba};/Hosts.*127-0-0-1/I!p}' file
1
potong 19 Jän. 2019 im 09:45

Vorausgesetzt, diese anchors sind genau und es gibt nichts vor # Query 1:,
versuchen Sie dies bitte:

awk -v RS="# Query 2" 'FNR<2 && !/# Hosts ip-127-0-0-1/'

Nach Ihrem eigenen Versuch zu urteilen, wenn Sie nur Zeilen möchten, beginnt dies mit einem Buchstaben in dem von Ihnen beschriebenen Block:

awk -v RS="# Query 2" -F"\n" 'FNR<2 && !/# Hosts ip-127-0-0-1/{for (i=1;i<=NF;i++) if($i~ "^[A-Za-z]") print $i}'

Wenn die Bedingungen etwas anders sind, hinterlassen Sie bitte einen Kommentar.

0
Tiw 19 Jän. 2019 im 05:33

Endgültige Arbeitslösung:

# Pull in isolated code block for each individual query and write to unique file.
TEMP='temp_file'
while read -r line; do
    if [[ $line =~ ^#[[:space:]]Query[[:space:]][0-9].* ]]; then
        new_query='1'
        ((counter++))
        echo "$line" > ${TEMP}_${counter}
    else
        new_query='0'
        echo "$line" >> ${TEMP}_${counter}
    fi
done < "${LONG_RUNNING_QUERIES}"

# Remove first file, as it only contains query statistics for all long running queries.
rm ${TEMP}_0

# For all files that don't contain the IP, group them together in one file.
QUERIES_TO_GRAB='master_file'
> $QUERIES_TO_GRAB
for i in $(ls -v1 temp_file_*); do
    match=$(grep "${IP_ADDY}" "$i")
    if [ -z "$match" ]; then
        cat $i >> $QUERIES_TO_GRAB
    fi
done
0
user3299633 20 Jän. 2019 im 19:47

Ich gehe davon aus, dass Ihre Abfragedatei wie folgt aussehen würde. Bitte versuchen Sie diese Perl-Lösung

$ cat query_ip.txt
# Query 1:
select a b c from
tab
# Hosts ip-127-8-8-1
where a = '1'

# Query 2:
select a b c from
tab2
# Hosts ip-127-0-0-1
where a = '1'

# Query 3:
select a b c from
tab3
# Hosts ip-127-9-9-1
where a = '1'

$  perl -0777 -ne ' $_.="# Query "; while( /(# Query.+?)(# Query.+)/smg ) { $x=$1 ; $_="$2"; print $x if not $x=~/ip-127-0-0-1/ } ' query_ip.txt
# Query 1:
select a b c from
tab
# Hosts ip-127-8-8-1
where a = '1'

# Query 3:
select a b c from
tab3
# Hosts ip-127-9-9-1
where a = '1'

$

Oder versuchen Sie dies.

$ perl -0777 -ne ' while( /(# Query.+?)(# Query.+|\Z)/smg ) { $x=$1 ; $_="$2"; print "$x\n" if not $x=~/ip-127-0-0-1/ } ' query_ip.txt
# Query 1:
select a b c from
tab
# Hosts ip-127-8-8-1
where a = '1'


# Query 3:
select a b c from
tab3
# Hosts ip-127-9-9-1
where a = '1'
$
0
stack0114106 21 Jän. 2019 im 09:31