6

我有一个像这样的文本文件:

      125
      126
      127    {
      566
      567
      568
      569       # blah blah
      570    {  #blah blah
      700
      701    {

数字是左对齐的,模式在增加的意义上总是相同的,最后有一个花括号。我只需要抓住起始数字。总是找到大括号并限制在序列结尾。文件的开头如图所示以“125”开头。

简而言之,我需要:

      125
      566
      700

我想出了什么:

      grep -A1 '{' | grep -v '{' | grep -oE '(^[0-9]+?)'

但这省略了 '125' 但我通过在头部附加一个换行符并插入一个{.

我希望将其简化为一个正则表达式。

欢迎提出建议和更好的算法

4

6 回答 6

4
awk 'BEGIN {p=1} p==1 {print $1;p=0} $0~/{/ {p=1}'

Output:
125
566
700

鉴于上述文件格式,您可以使用 awk 和一个变量/标志来跟踪您何时找到一个开口{

于 2012-07-10T12:45:53.237 回答
3
sed -n '1p;/{/{
N
s/.*\n\([0-9]\+\).*/\1/p
}' input_file
于 2012-07-10T12:43:45.760 回答
2

您可能需要调整正则表达式,但是:

awk '!k; { k = !/^ *[0-9]* *{/ }'

这将打印第一行以及与正则表达式匹配的行之后的任何行^ *[0-9]* *{ 您可能会简化事情并执行以下操作:

awk '!k;{k=$2!="{"}'

这将打印第一行和第二个字段是单个左大括号的行之后的任何行。

于 2012-07-10T12:44:17.247 回答
1

我会使用 awk 和一个标志来捕获大括号的存在并打印下一行。在开头设置标志,您将获得第一行。

未经测试,但类似于:

BEGIN {hasCurly = 1}
{ 
    if(hasCurly) 
        print $1;

    hasCurly = match($2,"^\{");
}
于 2012-07-10T12:41:01.740 回答
1

这是一个纯 bash 解决方案:

start=1
while read n rest; do
    if (( start )); then
        printf '%d\n' $n
        start=0
    elif [[ $rest = \{* ]]; then
        start=1
    fi
done < input
于 2012-07-10T12:48:41.327 回答
1

sed将在代码高尔夫比赛中获胜 =) :

sed -n '1p;/{/{n;p}' file

要删除号码后的所有内容,请使用:

sed -n '1{s/\s*\([0-9]\+\).*/\1/;p};/{/{n;s/\s*\([0-9]\+\).*/\1/;p}' file
于 2012-07-10T12:53:39.853 回答