Я обычно использую цикл while
для чего-то подобного, с петлей for
, вложенной внутри:
with open(filename) as f_in:
while True:
line = f_in.readline().strip()
if not line:
break
if line == "text":
data = [f_in.readline().strip() for i in range(15) if i in [2, 11, 13, 14]]
Это позволяет избежать загрузки всего файла перед его обработкой и особенно полезно, если у вас могут быть дополнительные строки между вашими сегментами данных, которые вам не нужно загружать, но они будут работать только в том случае, если не накладываются сегменты.
Обратите внимание, что этот код будет лишать ведущие и конечные пробелы из линии. Если вы хотите удалить только пробелы, вы можете использовать rstrip()
. Если вы хотите вообще не менять строку, вы можете попробовать совпадение с префиксом startswith()
или просто включить символ новой строки в ваше состояние.
Я предполагаю, что ваш файл запросов будет выглядеть так, как показано ниже. Пожалуйста, попробуйте это решение Perl
$ 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 ' Я предполагаю, что ваш файл запросов будет выглядеть так, как показано ниже. Пожалуйста, попробуйте это решение Perl
[110] или попробуйте это.
$ perl -0777 -ne ' while( /(# Query.+?)(# Query.+|\Z)/smg ) { $x=$1 ; Я предполагаю, что ваш файл запросов будет выглядеть так, как показано ниже. Пожалуйста, попробуйте это решение Perl
[110] или попробуйте это.
[111]="$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'
$
.="# Query "; while( /(# Query.+?)(# Query.+)/smg ) { $x=$1 ; Я предполагаю, что ваш файл запросов будет выглядеть так, как показано ниже. Пожалуйста, попробуйте это решение Perl
[110] или попробуйте это.
$ perl -0777 -ne ' while( /(# Query.+?)(# Query.+|\Z)/smg ) { $x=$1 ; Я предполагаю, что ваш файл запросов будет выглядеть так, как показано ниже. Пожалуйста, попробуйте это решение Perl
[110] или попробуйте это.
[111]="$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'
$
="$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'
$
или попробуйте это.
$ perl -0777 -ne ' while( /(# Query.+?)(# Query.+|\Z)/smg ) { $x=$1 ; Я предполагаю, что ваш файл запросов будет выглядеть так, как показано ниже. Пожалуйста, попробуйте это решение Perl
[110] или попробуйте это.
[111]="$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'
$
Окончательное рабочее решение:
# 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
Это может сработать для вас (GNU sed):
sed -n '/^# Query [0-9]*:/{:a;N;/^\s*$/M!ba;/Hosts.*127-0-0-1/I!p}' file
Используйте опцию sed -n
только для явной печати. Сфокусируйтесь на любой строке, которая начинается с # Query n*:
, где n*
означает ноль или более цифр (используйте [^:]*
, если это совпадение слишком конкретное). Собирайте текущие и последующие строки до (и включая) пустой строки. Проверьте коллекцию строк на строку 127-0-0-1
и, если ее нет, напечатайте коллекцию. Все остальные строки не будут напечатаны.
N.B. Коллекция включает в себя как строку запроса, так и пустую строку, это может быть не так, если последний запрос не имеет пустой строки в качестве последней строки файла. Это может быть удовлетворено улучшенной версией:
sed -n '/^# Query [0-9]*:/{:a;$!{N;/^\s*$/M!ba};/Hosts.*127-0-0-1/I!p}' file
Учитывая, что anchors
являются точными, и до # Query 1:
,
попробуйте, пожалуйста, ничего:
awk -v RS="# Query 2" 'FNR<2 && !/# Hosts ip-127-0-0-1/'
Судите по собственному усмотрению, если хотите, чтобы начинались только строки с буквой в блоке, который вы описали:
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}'
Если условия несколько иные, пожалуйста, оставьте комментарий.