如何使用SED找到第n个多行文本块



,所以我有一个文件,其中包含如下的块:

menuentry ... {
....
....
}
....
menuentry ... {
....
....
}

我需要在bash脚本中查看每个菜单条目的内容。我在SED方面的经验非常有限,但是通过A 详尽的搜索,我能够构建以下内容:

cat $file | sed '/^menuentry.*{/!d;x;s/^/x/;/x{1}/!{x;d};x;:a;n;/^}/!ba;q'

,我可以用我想获得nth块的任何数字替换{1}。这样可以正常工作,但是问题是我需要迭代任意次数:

numEntries=$( egrep -c "^menuentry.*{" $file ) 
for i in $( seq 1 $numEntries); do
    i=$( echo $i | tr -d 'n' ) # A google search indicated sed  encounters problems
                                # when a substituted variable has a trailing return char
    # Get the nth entry block of text with the sed statement from before, 
    # but replace with variable $i
    entry=$( cat $file | sed '/^menuentry.*{/!d;x;s/^/x/;/x{$i}/!{x;d};x;:a;n;/^}/!ba;q')
    # Do some stuff with $entry #
done

我尝试了围绕变量和sed语句周围的每种引号/双引号和牙套的组合以及我这样做的每一个方法,我都会遇到某种错误。正如我所说,我对SED并不了解太多,声明的Frankenstein正是我从各种Google搜索中共同完成了Mish-Mosh的内容,因此,任何帮助或解释都将不胜感激!

>

tia

sed用于单个线上的简单替换,即全部替换,而操纵文本的壳循环非常缓慢且难以编写。发明SED和Shell的人也为这样的任务发明了尴尬:

awk -v RS= 'NR==3' file

将打印第三个空白分隔的文本块,如您的问题所示。这将打印每个包含字符串" foobar"的块:

awk -v RS= '/foobar/' file

,您可能想做的其他任何事情都同样微不足道。

上面将使用任何Unix框上任何外壳中的任何尴尬有效,健壮和便便。例如:

$ cat file
menuentry first {
    Now is the Winter
    of our discontent
}
menuentry second {
    Wee sleekit cowrin
    timrous beastie,
    oh whit a panic's in
    thy breastie.
}
menuentry third {
    Twas the best of times
    Twas the worst of times
    Make up your damn mind
}

$ awk -v RS= 'NR==3' file
menuentry third {
    Twas the best of times
    Twas the worst of times
    Make up your damn mind
}
$ awk -v RS= 'NR==2' file
menuentry second {
    Wee sleekit cowrin
    timrous beastie,
    oh whit a panic's in
    thy breastie.
}
$ awk -v RS= '/beastie/' file
menuentry second {
    Wee sleekit cowrin
    timrous beastie,
    oh whit a panic's in
    they breastie.
}

除了使用S/Old/New和SED和/或使用S,G和P以外的S/Old/New以外的其他任何事情以外1970年代发明了尴尬。

如果上述对您不起作用,请编辑您的问题以提供更多真正代表性的样本输入和预期的输出。

如何拆分此功能?

首次搜索菜单条目开始的行(出于个人原因,我在这里使用grub,而不是grub2,适应您的需求(:

entrystarts=($(sed -n '/^menuentry.*/=' /boot/grub/grub.cfg))

然后,在第二步中,从数组中选择一个启动阀,对于n-th-entry ${entrystarts[$n]},然后从那里继续?Afaik,入口端很容易通过单个闭合的卷曲支架检测到。

for i in ${entrystarts[@]}
do 
    // your code here, proof of concept (note grub/grub2):
    sed -n "$i,/}/p" /boot/grub/grub.cfg
done

我看到了问题。您正在尝试使用$ i在单引号中。$我将在下面发布的$ i时将其留作$ i

'一个字符串'" $ twoStrings"'三字符串'

#!/bin/bash
#filename:grubtest.sh
numEntries=$( egrep -c "^menuentry.*{" "$1" )
i=0 
while [ $i -lt $numEntries ]; do
    i=$(($i+1))
    # Get the nth entry block of text with the sed statement from before, 
    entry=$( cat "$1" | sed '/^menuentry.*{/!d;x;s/^/x/;/x{'"$i"'}/!{x;d};x;:a;n;/^}/!ba;q')
    # Do some stuff with $entry #
    echo $entry|cut -d' -f2
done

这是跑步时返回了我的g子./grubtest.sh/etc/grub2.cfg

相关内容

  • 没有找到相关文章

最新更新