我有一个文本文件,如下所示:
# Query 1:
.
.
.
# Hosts ip-127-0-0-1
.
.
.
# Query 2:
.
.
在我的文件中可能有多个查询;我只想在我的IP值不确定时提取信息。
例如,在这里我要捕获以“#Query 1”开头,直到“#Query 2”之前的空格-但是,只有在主机ip与ip-127-不匹配的情况下,才需要执行此操作0-0-1。这不是完全匹配,因为ip-127-0-0-1可以在末尾附加其他文本,例如ip-127-0-0-1.notusefultext
我愿意使用awk,sed或python来解决此问题。
答案 0 :(得分:1)
这可能对您有用(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
的行集合,如果不存在,则打印该集合。其他所有行将不会打印。
该集合同时包含查询行和空行,如果最后一个查询没有空行作为文件的最后一行,则可能不是这种情况。这可以通过改进的版本来解决:
sed -n '/^# Query [0-9]*:/{:a;$!{N;/^\s*$/M!ba};/Hosts.*127-0-0-1/I!p}' file
答案 1 :(得分:0)
我假设您的查询文件如下所示。请尝试此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 ' $_.="# 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'
$
或尝试这个。
$ 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'
$
答案 2 :(得分:0)
鉴于这些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}'
如果条件有所不同,请发表评论。
答案 3 :(得分:0)
最终的解决方案:
# 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