抓取字符串所在的文本部分

时间:2019-01-19 00:53:28

标签: bash awk sed

我有一个文本文件,如下所示:

# 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来解决此问题。

4 个答案:

答案 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