【问题标题】:Split a string on a pattern using bash and/or awk使用 bash 和/或 awk 在模式上拆分字符串
【发布时间】:2014-04-15 15:04:46
【问题描述】:

我有一个格式如下的文件

file header string(s)
"section title" : [status]
unknown
text

"next section" : [different_status]
different
amount of

strings

我想把它分成几个部分,例如

file header string(s)

"section title" : [status]
unknown
text

"next section" : [different_status]
different
amount of

strings

虽然捕获该标头字符串并不重要。

如您所见,我可以依赖的拆分模式是

"string in quotes" : [string in square brackets]

这个分隔字符串也需要被捕获。

在 bash 脚本中执行此操作的简单方法是什么?我预测 awk 中的某些东西会做到这一点,但我的 awk-fu 很弱。

【问题讨论】:

  • 不是“分割”空行的“模式”吗?
  • 不完全。第一段之前没有空行,最后一段内有空行。小节标题后面的文字几乎可以是任何东西,所以我不能真正依赖那里的任何东西。从技术上讲,它可能类似于章节标题,但这不太可能。
  • 查看man csplit...
  • 我最终使用了 twalberg 对csplit 的建议,它完美而简单。

标签: regex bash shell awk


【解决方案1】:

Perl 解决方案:

#!/usr/bin/perl
use warnings;
use strict;

my $output = 0;
open my $OUT, '>', "section-$output" or die $!;
while (<>) {
    if (/"[^"]*" : \[[^\]]*\]/) {
        $output++;
        open $OUT, '>', "section-$output" or die $!;
    }
    print {$OUT} $_;
}

【讨论】:

  • 这个 perl 方法确实有效,但我更喜欢可以更轻松地合并到 bash 脚本中的东西。
【解决方案2】:

这在纯 Bash 中可以解决问题:

#!/bin/bash

while read line; do
    [[ "$line" =~ "^\"[^\"]*\" : \[[^]]*\]" ]] && i=$(( ++i ))
    [[ $i > 0 ]] && echo "SECTION_$i: " $line
done < $1

更新:改进的正则表达式。

【讨论】:

    【解决方案3】:

    应该是awk 中的单行符。假设我正确地解释了你的跳水线,那么这个呢?

    awk '/^"[^"]+" : \[[^]]+\]$/ { printf("\n"); } 1' inputfile > outputfile
    

    末尾的“1”是表示“打印当前行”的快捷方式。如果当前行与模式匹配,则它之前的条件和表达式对将插入空白。

    你也可以在sed one-liner 中交替做同样的事情:

    sed -r '/^"[^"]+" : \[[^]]+\]$/{x;p;x;}' inputfile > outputfile
    

    这使用了 sed 的“保持空间”的魔力。您可以man sed 详细了解x 的工作原理。

    【讨论】:

      猜你喜欢
      • 2016-01-27
      • 1970-01-01
      • 2011-04-15
      • 1970-01-01
      • 2014-12-22
      • 1970-01-01
      • 1970-01-01
      • 2013-01-15
      • 1970-01-01
      相关资源
      最近更新 更多