如何对此 ASCII 文件中的这些行进行分类

如何对此 ASCII 文件中的这些行进行分类

我的 ASCII 文件是这样的:

a
1 2 3
1223
b
1 2 3 5
3344
1223
c
1 2 34
a
4 5
c
123

如何分别收集 a、b、c 下面的行?

问:我该怎么做才能得到下面的几行?

a
1 2 3
1223
4 5

答案1

awk '/^[a-z]$/ { f = $1=="a" ; if (!c++) print ; next }; f'

答案2

啊,awk与我迄今为止在这里看到的其他解决方案不同,仅使用一次数据传递,使事情变得更加容易:

/^[a-z]/{key=$0;} 
/^[0-9]/{if (key in res){ res[key]=res[key] "\n" $0;} else {res[key]=$0;}} 
END {for(key in res){
    print key; 
    print res[key];
    }}

如果你想要sed+frills-only,这似乎有效:

 cat data.txt | sed -e '/^a/,/^[b-z]/!d' | sed -e '2,${ /^[a-z]/d }'

(是的,这是一个对猫的无用利用 出于教学原因,即当文件位于管道中间的某个位置时,我会感到困惑。)

第一个考虑以字母 开头的行sed开头和结尾的所有范围(包括)。它否定该范围(the ),然后删除所有匹配的内容,所以我们只剩下ab-z!

a
1 2 3
1223
b
a
4 5
c

第二个sed仅查看从第 2 行到文件末尾的范围(以维护标题a),并在其中删除所有以字母 开头的行a-z,只留下数字行:

a
1 2 3
1223
4 5

要获取所有标题的列表,我会尝试grep '^[a-z]' | sort -u。所以整个野兽是:

for key in $(grep  '^[a-z]' data.txt | sort -u ); do 
    cat data.txt | sed -e "/^$key/,/^[b-z]/\!d" | sed -e '2,${ /^[a-z]/d }'  ; 
done

答案3

awk '
/^[a-z]$/{
  i=$0
  next
  }
{
  A[i]=A[i] "\n" $0
  }
END{
  for (j in A)
    print j A[j]
  }'

正如你所看到的,它是以下的简化变体@Ulrich Schwarz 脚本:对于仅包含 1 个小写字母的行,将此字母作为索引i并开始新行循环。接下来,A根据i脚本前一部分使用\newline 分隔符确定的索引,将所有剩余行(不是“仅包含 1 个小写字母”,因为它之前已操作过)放入关联数组中。当脚本传递所有行(到达)时,然后按索引END打印数组。Ai

答案4

这是一个awk不遗余力防止打印第二个的解决方案a

awk '$1 == "a" { if (!head) print; n=head=1; next } $1 !~ /^[0-9]/ { n=0 } n' ascii_file

替换"a""b"以获得这些结果等。

输出:

a
1 2 3
1223
4 5

如果你想要一个循环,你可以这样做:

for letter in a b c; do
  echo
  awk -v letter="$letter" '$1 == letter { if (!head) print; n=head=1; next } $1 !~ /^[0-9]/ { n=0 } n' /tmp/a
done

会有这样的输出:

a
1 2 3
1223
4 5

b
1 2 3 5
3344
1223

c
1 2 34
123

(注意这一echo行。它在每个查询的命中之间进行分隔。我构建这个答案是为了让您可以按字母查询,这是我对这个问题的理解。)

相关内容