Regex 在图案之间打印几行(第一个图案不唯一)

Regex 在图案之间打印几行(第一个图案不唯一),regex,bash,awk,sed,grep,Regex,Bash,Awk,Sed,Grep,需要sed/awk/grep/任何可以解决我任务的帮助。 我有一个大文件,我需要从中提取多个连续行 我有开始模式: 和结束模式: 中间有几行,如下所示: <DN>234</DN> <DD>sdfsd</DD> <BR>456456</BR> <COL>6575675 sdfsd</COL> <RAC>456464</RAC> <GR>sdfsdfsFFFDd<

需要sed/awk/grep/任何可以解决我任务的帮助。 我有一个大文件,我需要从中提取多个连续行

我有开始模式:

和结束模式:

中间有几行,如下所示:

<DN>234</DN>
<DD>sdfsd</DD>
<BR>456456</BR>
<COL>6575675 sdfsd</COL>

<RAC>456464</RAC>
<GR>sdfsdfsFFFDd</GR>
234
自卫队

456456
6575675自卫队 456464 SDFSDFSFDD
我试过这个:

sed -n '/\<DN\>/,/\<\/GR\>/p'
sed-n'/\/,/\/p'
和其他几个(使用awk和sed)。 它可以正常工作,但问题是源文件可能包含以
开头的行,而在一组行的末尾不包含
,然后以另一个和正常结尾的部分开始:

<DN>234</DN> - unneded DN
<AB>sdfsd</AB>
<DC>456456</DC>
<EF>6575675 sdfsd</EF>
....really large piece of unwanted text here....

<DN>234</DN>
<DD>sdfsd</DD>
<BR>456456</BR>
<COL>6575675 sdfsd</COL>

<RAC>456464</RAC>
<GR>sdfsdfsFFFDd</GR>
<RAC>456464</RAC>
<GR>sdfsdfsFFFDd</GR>
234-无编号DN
自卫队
456456
6575675自卫队
…这里有一大块不需要的文字。。。。
234
自卫队

456456
6575675自卫队 456464 SDFSDFSFDD 456464 SDFSDFSFDD
如何只提取需要的行,而忽略包含
的日志的垃圾段,而不结束

接下来,我需要将多行片段从
转换为
到一个单行文件,从
开始,以
结束。
任何帮助都将不胜感激。我被卡住了

你可以使用
pcregrep
工具来实现这一点

$ pcregrep -o -M '(?s)(?<=^|\s)<DN>(?:(?!<DN>).)*?</GR>(?=\n|$)' file
<DN>234</DN>
<DD>sdfsd</DD>
<BR>456456</BR>
<COL>6575675 sdfsd</COL>

<RAC>456464</RAC>
<GR>sdfsdfsFFFDd</GR>

$pcregremp-o-M'(?s)(?您可以使用
pcregremp
工具进行此操作

$ pcregrep -o -M '(?s)(?<=^|\s)<DN>(?:(?!<DN>).)*?</GR>(?=\n|$)' file
<DN>234</DN>
<DD>sdfsd</DD>
<BR>456456</BR>
<COL>6575675 sdfsd</COL>

<RAC>456464</RAC>
<GR>sdfsdfsFFFDd</GR>
$pcregrep-o-M'(?s)(?
awk'
#以“”开头的行开始匹配。
/^/ {
#如果我们看到了一个开始,却没有一个相匹配的结束,那就扔掉我们所保存的一切。
如果(dn){
d=“”
}
#标记位于“”元素中。
dn=1
#保存当前行。
d=0美元
下一个
}
#以“$”结尾的行结束匹配(但仅当我们当前处于匹配中时)。
dn&&/$/{
#我们不再是一个元素了。
dn=0
#打印出我们保存的行和当前行。
打印文件“%s%s%s\n”,d,OFS,$0
#重置保存的内容。
d=“”
下一个
}
#如果我们在一个元素中并且已经保存了内容,则将当前行附加到内容中(由OFS分隔)。
dn&d{
d=d OFS$0
}
"档案"
awk'
#以“”开头的行开始匹配。
/^/ {
#如果我们看到了一个开始,却没有一个相匹配的结束,那就扔掉我们所保存的一切。
如果(dn){
d=“”
}
#标记位于“”元素中。
dn=1
#保存当前行。
d=0美元
下一个
}
#以“$”结尾的行结束匹配(但仅当我们当前处于匹配中时)。
dn&&/$/{
#我们不再是一个元素了。
dn=0
#打印出我们保存的行和当前行。
打印文件“%s%s%s\n”,d,OFS,$0
#重置保存的内容。
d=“”
下一个
}
#如果我们在一个元素中并且已经保存了内容,则将当前行附加到内容中(由OFS分隔)。
dn&d{
d=d OFS$0
}
"档案"
awk'
/^/{n=1}
n{lines[n++]=$0}
n&&/$/{
对于(i=1;i
awk'
/^/{n=1}
n{lines[n++]=$0}
n&&/$/{
对于(i=1;i和bash:

fun () 
{ 
    local line output;
    while IFS= read -r line; do
        if [[ $line =~ ^'<DN>' ]]; then
            output=$line;
        else
            if [[ -n $output ]]; then
                output=$output$'\n'$line;
                if [[ $line =~ '</GR>'$ ]]; then
                    echo "$output";
                    output=;
                fi;
            fi;
        fi;
    done
}

fun <file
fun()
{ 
本地线路输出;
当IFS=读取-r行时;执行
如果[[$line=~^''],则
输出=$行;
其他的
如果[[-n$output]];则
output=$output$'\n'$行;
如果[[$line=~''$]];则
回显“$output”;
输出=;
fi;
fi;
fi;
完成
}
bash的乐趣:

fun () 
{ 
    local line output;
    while IFS= read -r line; do
        if [[ $line =~ ^'<DN>' ]]; then
            output=$line;
        else
            if [[ -n $output ]]; then
                output=$output$'\n'$line;
                if [[ $line =~ '</GR>'$ ]]; then
                    echo "$output";
                    output=;
                fi;
            fi;
        fi;
    done
}

fun <file
fun()
{ 
本地线路输出;
当IFS=读取-r行时;执行
如果[[$line=~^''],则
输出=$行;
其他的
如果[[-n$output]];则
output=$output$'\n'$行;
如果[[$line=~''$]];则
回显“$output”;
输出=;
fi;
fi;
fi;
完成
}
乐趣这可能适合你(GNU-sed):

sed-n'/{h;b};x;/./G;x;/这可能适合您(GNU-sed):


sed-n'/{h;b};x;//G;x;/谢谢您的回复!不幸的是,您的建议对实际文件不起作用。可能是因为系统将其视为二进制文件,我必须在grep命令中添加-a选项以使其起作用。但是对于pcregrep没有这样的选项。您能将确切的文件内容发布到pastebin中吗?恐怕它太大了。s每一百兆字节的文件只包含我需要提取的几行有价值的数据。它来自生产系统,包含客户机数据。这一行最终对我有用:pcregrep--buffer size=100000000-o-M'(?s)(?谢谢你的回复!不幸的是,你的建议对实际文件不起作用。可能是因为系统将其视为二进制文件,我必须在grep命令中添加-a选项以使其起作用。但是对于pcregrep没有这样的选项。你能在pastebin或你的问题中发布确切的文件内容吗?恐怕它太大了ndred MB的文件只包含我需要提取的几行有价值的数据。它来自生产系统,包含客户机数据。这一行最终对我有用:pcregrep--buffer size=100000000-o-M'(?s)(?哇,谢谢,太棒了。我甚至不知道如何使用它。我应该把它复制到脚本中吗?如果我这样做,什么也不会发生。系统运行几秒钟,然后什么也不打印。但是如果我手动或用grep-a检查,文件确实包含匹配的数据。文件是否有DOS行结尾?
grep'$”
是否找到匹配的行?“grep”^'`?实际上文件没有行尾(至少notepad++不显示任何CRLF或类似的内容),它是一种二进制文件,但包含大量文本,并混合了二进制数据。grep-a“^”20140905.log找到许多匹配项。grep“$”20140905.log-不t@IvanBondarets如果文件不是“文本文件”那么在脚本上使用文本工具就不那么可靠了。也就是说,你可以尝试在脚本中使用
/
(d
sed -n '/<DN>/{h;b};x;/./G;x;/<\/GR/{x;/./p;z;x}' file