【问题标题】:Extracting lines between two lines starting with "$" with sed用 sed 提取以“$”开头的两行之间的行
【发布时间】:2017-01-08 14:14:47
【问题描述】:

我有一个大文本文件,其中包含一些数据,如下所示:

$  10c20
data
data
.
.
data
data
$  10c21
data
data
.
.
data
data
$  10c22
.
.

我想在每两个注释行之间提取数据(以“$”开头)并将该数据块存储在一个新文件中,然后将下一个块存储到文件末尾。我尝试了“sed”,但我无法获得我需要的东西。有什么想法吗?

想要的输出:

$  10c20
    data
    data
    .
    .
    data
    data

$  10c21
    data
    data
    .
    .
    data
    data 

$  10c22
    data
    data
    .
    .
    data
    data 

和...

【问题讨论】:

  • 很难/不可能使用 sed 进行多行操作。最多连续两行是我“轻松”设法工作的内容。任何语言都有可能吗?
  • 请将该示例输入的所需输出也添加到您的问题中。
  • @kabanus 我已经做了类似的事情,只有两条不同模式的行,但我不知道该怎么做
  • 我刚刚注意到this 类似,不确定是否重复。
  • 你为什么这么说:“不同的是我在注释行的开头有相同的字符”?我第一次理解你很好。无论如何,它似乎what you asked and what you want are two different things。如果您要编辑,我会帮忙,否则我会遇到一些麻烦。

标签: bash sed


【解决方案1】:

如果您不想要像 Python/Perl 这样的“高级”语言,有一个通用的内置 csplit,但您需要同意使用文件:

/home/.../RGS/tmp>csplit bla  '/^\$/' {*} 
0
21
21
21
21
/home/.../RGS/tmp>cat xx00
/home/.../RGS/tmp>cat xx01
$  10c20
data1
data1
/home/.../RGS/tmp>cat xx02
$  10c21
data2
data2
/home/.../RGS/tmp>cat xx03
$  10c22
data3
data3
/home/.../RGS/tmp>cat xx04
$  10c23
data4
data4
/home/.../RGS/tmp>

bla 在哪里:

$  10c20
data1
data1
$  10c21
data2
data2
$  10c22
data3
data3
$  10c23
data4
data4

最后只是rm xx*

编辑

文件准备好后,在 bash 中:

for inp in xx*; do
     cat $inp | toSomeComputations &
     #Or
     toSomeComputations $inp &
 done

当然,您可以使用其他东西来使这个循环并行。

【讨论】:

  • 我认为你不明白我想要什么,两行注释之间的数据是可变的和巨大的,不能使用你的代码。还是谢谢
  • 这适用于“可变且庞大”的数据,但也许您应该考虑使用更简单语言的脚本。如果您不清楚拆分后如何处理文件,我会编辑。
  • 它是一个大规模的并行计算程序,所以它没有帮助,我只想将提取的块粘贴到另一个文件中作为上述程序的输入。
  • 什么是平行的?你为什么要为此使用 Linux 命令?您需要在问题中写下所有这些内容,而不是事后回答答案。请用整个流程重新编写问题。很容易循环这些文件并将它们 cat/give 到另一个进程...
  • 我从未说过我想使用 bash 进行并行计算!我刚刚说过我想将提取的数据块复制并粘贴到另一个文件中,该文件是另一个程序的输入。 后者将在不知道输入是如何产生的情况下进行并行计算!我刚刚回答了 Lars 关于计算的问题
【解决方案2】:

这是一个 GNU awk 脚本,它重现了@kabanus 的答案。当@kabanus 给出的答案对您不起作用时,我不知道这对您有什么帮助,但就是这样。

script.awk

function doit( header ) { 
    # filename with leading zeros in number
    outFileName = sprintf("out_%04d", NR-1)
    printf("%s%s", header, $0 ) > outFileName
    # now lets run a command on that file, e.g. cat
    system("cat " outFileName )
}

# set record split by the dollar lines
BEGIN   { RS="[$][^\n]+" }

{ 
  # on NR == 1 ( the first record ) oldRT is empty
  # we need to store RT and use oldRT when we output $0 
  # for the next record
  if( oldRT ) doit( oldRT )
  oldRT = RT
}

像这样运行它:awk -f script.awk yourfile

【讨论】:

  • 如何将提取的每个数据块打印到单独的文件中? (考虑for循环)
  • 请稍等,我离开键盘了。
【解决方案3】:

你只需要:

awk '
function doCalculation() {
    # do whatever you want with the multi-line string "buf" then
    printf "%s", buf
    buf = ""
}
/^\$/ { doCalculation() }
{ buf = buf $0 ORS }
END { doCalculation() }
' file

如果这样更方便,您可以将 buf 设为数组而不是多行字符串,但两种方式的逻辑都相同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 2017-04-23
    • 2018-01-08
    • 1970-01-01
    • 1970-01-01
    • 2021-06-25
    相关资源
    最近更新 更多