筛选或通过管道传输文件的某些部分


14

我有一个输入文件,其中的某些部分用开始和结束标记来分隔,例如:

line A
line B
@@inline-code-start
line X
line Y
line Z
@@inline-code-end
line C
line D

我想对此文件进行转换,以使X,Y,Z行通过某些命令(nl例如)过滤,但其余各行保持不变。请注意,nl(数字行)在行之间累积状态,因此并不是将静态转换应用于X,Y,Z行。(编辑:有人指出,nl在不需要积累状态的模式可以工作,但我只是用nl作为一个例子来简化这个问题在现实中的命令是一个更复杂的自定义脚本。什么我期待对于将标准过滤器应用于输入文件的子部分的问题的通用解决方案

输出应如下所示:

line A
line B
     1 line X
     2 line Y
     3 line Z
line C
line D

文件中可能有几个此类需要转换的部分。

更新2我最初没有指定如果有更多的部分应该发生什么,例如:

line A
line B
@@inline-code-start
line X
line Y
line Z
@@inline-code-end
line C
line D
 @@inline-code-start
line L
line M
line N
@@inline-code-end

我的期望是,仅需在给定的部分内保持状态,即可得出:

line A
line B
     1 line X
     2 line Y
     3 line Z
line C
line D
     1 line L
     2 line M
     3 line N

但是,我认为将问题解释为要求将状态跨节保留是正确的,并且在许多情况下很有用。

结束更新2

我的第一个想法是构建一个简单的状态机来跟踪我们所在的部分:

#!/usr/bin/bash
while read line
do
  if [[ $line == @@inline-code-start* ]]
  then
    active=true
  elif [[ $line == @@inline-code-end* ]]
  then
    active=false
  elif [[ $active = true ]]
  then
    # pipe
  echo $line | nl
  else
    # output
    echo $line
  fi
done

与我一起运行:

cat test-inline-codify | ./inline-codify

这是行不通的,因为对的每次调用nl都是独立的,因此行号不会增加:

line A
line B
     1  line X
     1  line Y
     1  line Z
line C
line D

我的下一个尝试是使用fifo:

#!/usr/bin/bash
mkfifo myfifo
nl < myfifo &
while read line
do
  if [[ $line == @@inline-code-start* ]]
  then
    active=true
  elif [[ $line == @@inline-code-end* ]]
  then
    active=false
  elif [[ $active = true ]]
  then
    # pipe
    echo $line > myfifo
  else
    # output
    echo $line
  fi
done
rm myfifo

这样可以给出正确的输出,但是顺序错误:

line A
line B
line C
line D
     1  line 1
     2  line 2
     3  line 3

可能正在进行一些缓存。

我要解决所有这些错误吗?这似乎是一个非常普通的问题。我觉得应该有一个简单的管道可以解决这个问题。


nl不必积累状态。看nl -d,并检查您man/ info关于信息页面nl部分分隔符
mikeserv 2015年

nl只是一个例子。就我而言,我正在运行自定义脚本而不是nl。
詹姆斯·斯克里文

在这种情况下,请说明您的脚本在做什么。
terdon

我在问题中澄清了我仅用nl作示例过滤器。我以为可以通过掩盖过滤器确切执行的详细信息来简化问题,但我可能只会引起更多的混乱。实际上,我正在通过代码突出显示过滤该部分,以用于本地静态博客生成器。现在,我正在使用gnu source-highlight,但这可能会改变,并且我可能会添加更多过滤器,例如格式化程序。
James Scriven 2015年

Answers:


7

我会同意你的看法-这可能一个普遍的问题。但是,某些常用的实用程序具有一些处理它的功能。


nl

nl中,例如,分离输入到逻辑页作为-d由两个字符elimited 部定界符。一行上出现的3个单独指示航向的开始,两个身体和一个页脚。它用输出中的空行替换输入中发现的所有空行,这是它曾经打印过的唯一空行

我将您的示例更改为包含另一部分,并将其放入./infile。所以看起来像这样:

line A
line B
@@inline-code-start
line X
line Y
line Z
@@inline-code-end
line C
line D
@@start
line M
line N
line O
@@end

然后我运行以下命令:

sed 's/^@@.*start$/@@@@@@/
     s/^@@.*end$/@@/'  <infile |
nl -d@@ -ha -bn -w1

nl可以被告知在逻辑页面之间累积状态,但是默认情况下不这样做。取而代之的是,它将根据样式部分来编号其输入的行。所以,-ha手段号的所有线,-bn意味着没有车身线条 -因为它在一开始时的身体状态。

直到我了解了这一点后,我便习惯将其nl用于任何输入,但是在意识到这nl可能会根据其默认的-d分隔符使输出失真时,\:我学会了对其进行更加谨慎的操作,并开始使用grep -nF ''未经测试的输入。但是那天学到的另一个经验教训是,nl可以将其非常有用地应用到其他方面(例如这一方面),如果您只需稍微修改一下其输入内容,就像我sed上面所做的那样。

输出值

  line A
  line B

1       line X
2       line Y
3       line Z

  line C
  line D

1       line M
2       line N
3       line O

这是更多有关nl-您是否在上面注意到除编号的行以外的所有行如何以空格开头?当nl数字行时,它会在每个数字的开头插入一定数量的字符。对于那些行,它不会编号-甚至是空格-它总是通过在未编号的行的开头插入(-width count + -s分隔符len)*空格来匹配缩进。这使您可以轻松地通过将未编号的内容与已编号的内容进行比较来精确地复制它们。当您考虑nl将其输入划分为逻辑部分,并且可以-s在其编号的每一行的开头插入任意曲调时,就很容易处理其输出:

sed 's/^@@.*start$/@@@@@@/
     s/^@@.*end/@@/; t
     s/^\(@@\)\{1,3\}$/& /' <infile |
nl -d@@ -ha -bn -s' do something with the next line!
'

上面的打印...

                                        line A
                                        line B

 1 do something with the next line!
line X
 2 do something with the next line!
line Y
 3 do something with the next line!
line Z

                                        line C
                                        line D

 1 do something with the next line!
line M
 2 do something with the next line!
line N
 3 do something with the next line!
line O

GNU sed

如果nl不是您的目标应用程序,那么GNU sed可以e根据匹配为您执行一个任意的shell命令。

sed '/^@@.*start$/!b
     s//nl <<\\@@/;:l;N
     s/\(\n@@\)[^\n]*end$/\1/
Tl;e'  <infile

上面sed收集了模式空间中的输入,直到它有足够的空间成功地通过替代Test并停止b:label 放回牧场。当这样做时,它将e对其其余所有模式空间的nl输入作为<<此处文档表示为Xecute 。

工作流程如下:

  1. /^@@.*start$/!b
    • 如果^整条生产线$!没有/匹配/上面的图案,那么它是b在我们只用一系列的线,这与模式开始工作,所以从这个角度-办牧场出来的剧本和autoprinted。
  2. s//nl <<\\@@/
    • s//字段/代表最后一次sed尝试匹配的地址-因此,此命令代替整@@.*startnl <<\\@@
  3. :l;N
    • :命令定义了一个分支标签-在这里我设置了一个名为:label的标签。的N电话分机命令追加输入到图案空间中的下一行后跟一个\newline字符。这是\nsed模式空间中获取ewline 的仅有几种方法之一\n-ewline字符是肯定会sed做一段时间的der的定界符。
  4. s/\(\n@@\)[^\n]*end$/\1/
    • s///一后ubstitution只能是成功的开始遇到并仅在第一以下一个的发生线。它只会作用于模式空间,在该模式空间中,最后的\newline会紧随其后,然后@@.*end标记$模式空间的尽头。当它起作用时,它将用\1第一\(\)或替换整个匹配的字符串\n@@
  5. Tl
    • TEST命令转移到一标签(如果有的话),如果自上次输入线被拉入模式空间没有发生成功的替换(像我一样W / N。这意味着每当将\newline添加到与您的结束定界符都不匹配的模式空间时,Test命令就会失败并分支回到:label,这会导致sed拉入Next行并循环直到成功。
  6. e

    • 当结束比赛的替换成功并且脚本没有为失败的Test 返回分支时,sede执行如下所示的命令l

      nl <<\\@@\nline X\nline Y\nline Z\n@@$

您可以通过将最后一行修改为来亲自查看Tl;l;e

它打印:

line A
line B
     1  line X
     2  line Y
     3  line Z
line C
line D
     1  line M
     2  line N
     3  line O

while ... read

最后一种方法(也许是最简单的方法)是使用while read循环,但这是有充分理由的。外壳(尤其是bash外壳)通常在处理大量输入或源源不断的输入时非常糟糕。这也很有意义-shell的工作是逐字符处理输入的内容,并调用其他可以处理较大内容的命令。

但是,关于它的作用的重要一点是,外壳程序一定不能 read过多地输入内容-它被指定为缓冲输入或输出,以至于它消耗大量的时间或没有足够的时间进行中继,从而导致缺少所调用的命令-到字节。因此,read这是一个出色的输入测试 - return提供有关是否还有剩余输入的信息,您应该调用下一条命令来读取它-但这通常不是最好的方法。

但是,这是一个示例,说明如何使用read 其他命令来同步处理输入:

while   IFS= read -r line        &&
case    $line in (@@*start) :;;  (*)
        printf %s\\n "$line"
        sed -un "/^@@.*start$/q;p";;
esac;do sed -un "/^@@.*end$/q;=;p" |
        paste -d: - -
done    <infile

每次迭代的第一件事就是read拉一条线。如果成功,则表示循环尚未达到EOF,因此在case匹配起始定界符的do情况下立即执行该块。否则,printf打印$lineread并被sed调用。

sed将完全撕裂p每行直到遇到开始标记-当它q完全输入时。该-unbuffered开关是必要的GNU sed因为它能够缓冲相当贪婪,否则,而是-根据规范-其他POSIX sedS的关系没有任何特殊考虑工作-只要<infile是一个普通文件。

当使用第一个sed quit时,shell执行do循环块-调用另一个循环,该循环sed打印每行,直到遇到结束标记。它将输出通过管道传输到paste,因为它在各自的行上分别打印行号。像这样:

1
line M
2
line N
3
line O

paste然后将它们粘贴到:字符上,整个输出如下所示:

line A
line B
1:line X
2:line Y
3:line Z
line C
line D
1:line M
2:line N
3:line O

这些仅是示例-可以在此处的测试或do块中完成任何操作,但第一个实用程序一定不能消耗过多的输入。

所有涉及的实用程序都读取相同的输入-并打印其结果-分别轮流使用。这种东西可能很难找到窍门-因为不同的用途将缓冲比别人多-但你通常可以依靠ddheadsed做正确的事(虽然,对于GNU sed,你所需要的命令行开关)和您应该始终能够依靠read-因为从本质上讲,它非常慢。这就是上述循环在每个输入块中仅调用一次的原因。


我测试了sed您给出的第二个示例,它确实起作用了,但是我确实很难理解语法。(我的sed非常弱,通常仅限于s / findthis / replacethis / g。我必须努力坐下并真正理解sed。)
James Scriven 2015年

@JamesScriven-我只是为了更好地解释而进行了编辑。让我知道是否有帮助。我还对命令进行了很多更改-现在将其分成较小的,更合理的部分。
mikeserv

4

一种可能性是使用vim文本编辑器执行此操作。它可以通过shell命令通过管道传送任意节。

一种方法是使用行号:4,6!nl。此ex命令将在第4-6行(含第6行)上运行nl,以实现示例输入所要的内容。

另一种更具交互性的方法是,使用行选择模式(shift-V)和箭头键或搜索来选择适当的行,然后使用:!nl。您的示例输入的完整命令序列可能是

/@@inline-code-start
jV/@@inline-code-end
k:!nl

这不是很适合自动化(使用sed的答案对此更好),但是对于一次性编辑,不必诉诸20行shellscript非常有用。

如果您不熟悉vi(m),则至少应该知道在进行这些更改之后,您可以使用来保存文件:wq


是的,vim很棒!但是,在这种情况下,我正在寻找一种可编写脚本的解决方案。
James Scriven 2015年

@JamesScriven,任何说vim的人都无法确定脚本。首先创建一个项目目录,并在该目录中从您的主目录复制所有vim的启动文件(ln -s工作正常,除了我们将要修改的.vimrc和可能充满噪音的.viminfo)。将将完成工作的函数定义添加到新的.vimrc文件中,然后将vim称为HOME=$(pwd) vim -c 'call Mf()' f。如果您使用的是xargs,则可能要在专用的xserver上使用gvim来防止损坏tty(vnc与视频卡无关,可以对其进行监视)。
hildred

@hildred Hmmm ...我不能只使用[XSendEvent](tronche.com/gui/x/xlib/event-handling/XSendEvent.html)模拟鼠标单击到Vim吗?
James Scriven 2015年

2

我能想到的最简单的解决方法是不使用nl而是自己计算行数:

#!/usr/bin/env bash
while read line
do
    if [[ $line == @@inline-code-start* ]]
    then
        active=true
    elif [[ $line == @@inline-code-end* ]]
    then
        active=false
    elif [[ $active = true ]]
    then
        ## Count the line number
        let num++;
        printf "\t%s %s\n" "$num" "$line"
    else
        # output
        printf "%s\n" "$line"
    fi
done

然后,在文件上运行它:

$ foo.sh < file
line A
line B
    1 line X
    2 line Y
    3 line Z
line C
line D

谢谢terdon。我更新了问题以澄清我正在寻找一种通用解决方案来过滤输入的小节,而不是编号行的特定示例。也许更好的示例命令是“ tac”(反向行)
James Scriven 2015年

2

如果您的目标是将整个代码块发送到单个流程实例,则可以累积行并延迟管道,直到到达代码块的末尾:

#!/bin/bash

acc=""

while read line
do
  if [[ $line == @@inline-code-start* ]]
  then
    active=true
    acc=""
  elif [[ $line == @@inline-code-end* ]]
  then
    active=false
    # Act on entire block of code
    echo "${acc:1}" | nl  # Chops off first leading new-line character using ${VAR:1}
  elif [[ $active = true ]]
  then
    acc=$( printf "%s\n%s" "$acc" "$line" )
  else
    # output
    echo $line
  fi
done

这会为输入文件产生以下内容,该文件重复测试用例3次:

line A
line B
     1  line X
     2  line Y
     3  line Z
line C
line D
line A
line B
     1  line X
     2  line Y
     3  line Z
line C
line D
line A
line B
     1  line X
     2  line Y
     3  line Z
line C
line D

要对代码块进行其他操作(例如,反转然后进行编号),只需将其通过其他管道传递即可:echo -E "${acc:1}" | tac | nl。结果:

line A
line B
     1  line Z
     2  line Y
     3  line X
line C
line D

或字数echo -E "${acc:1}" | wc

line A
line B
      3       6      21
line C
line D

2

编辑添加了一个选项来定义用户提供的过滤器

#!/usr/bin/perl -s
use IPC::Open2;
our $p;
$p = "nl" unless $p;    ## default filter

$/ = "\@\@inline-code-end\n";
while(<>) { 
   chomp;
   s/\@\@inline-code-start\n(.*)/pipeit($1,$p)/se;
   print;
}

sub pipeit{my($text,$pipe)=@_;
  open2(my $R, my $W,$pipe) || die("can open2");
  local $/ = undef;
  print $W $text;
  close $W;
  return <$R>;
}

默认情况下,过滤器为“ nl”。要通过某些用户提供的命令来更改过滤器使用选项“ -p”:

codify -p="wc" file

要么

codify -p="sed -e 's@^@ ║ @; 1s@^@ ╓─\n@; \$s@\$@\n ╙─@'" file

最后一个过滤器将输出:

line A
line B
 ╓─
  line X
  line Y
  line Z
 ╙─
line C
line D

更新1 使用IPC :: Open2存在缩放问题:如果超出缓冲区大小,则可能会阻塞。(在我的机器中,如果64K对应于10_000 x“ Y线”,则管道缓冲区的大小)。

如果我们需要更大的东西(是否需要更多的10000条“ Y线”):

(1)安装使用 use Forks::Super 'open2';

(2)或用以下方式代替函数pipeit:

sub pipeit{my($text,$pipe)=@_;
  open(F,">","/tmp/_$$");
  print F $text;
  close F;
  my $out = `$pipe < /tmp/_$$ `;
  unlink "/tmp/_$$";
  return $out;
}

这太酷了。我猜想的窍门是,您不是逐行处理(通过重命名$/s标志),而是使用e标志对外部命令进行实际调用。我真的很喜欢第二个(ascii艺术)示例!
James Scriven 2015年

我注意到的是,这似乎没有超出该小节中的几千行。我怀疑这与将小节视为一大段文字有关。
James Scriven 2015年

谢谢。是:`/ e` = eval; /s=(“。”表示(.|\n)); $/重新定义寄存器分隔符。
JJoao 2015年

@JamesScriven,您说对了(管道阻塞)。让我测试发生了什么...
JJoao 2015年

@JamesScriven,请参阅我的更新...
JJoao 2015年

1

这是awk的工作。

#!/usr/bin/awk -f
$0 == "@@inline-code-start" {pipe = 1; next}
$0 == "@@inline-code-end" {pipe = 0; close("nl"); next}
pipe {print | "nl"}
!pipe {print}

当脚本看到开始标记时,它指出应该开始管道到中nl。当pipe变量为true(非零)时,输出通过管道传递到nl命令;当变量为假(未设置或为零)时,将直接打印输出。第一次遇到每个命令字符串的管道结构时,将管道命令分叉。使用相同字符串对管道操作员进行的后续评估将重用现有管道;不同的字符串值将创建不同的管道。该close函数关闭给定命令字符串的管道。


这与使用命名管道的Shell脚本本质上是相同的逻辑,但是更容易说明,并且关闭逻辑正确完成。您需要在正确的时间关闭管道,以使nl命令退出并刷新其缓冲区。您的脚本实际上关闭管道为时过早:管道在第一个echo $line >myfifo执行完成后立即关闭。但是,如果该nl命令在下一次脚本执行之前得到一个时间片,则该命令只会看到文件的结尾echo $line >myfifo。如果您有大量数据,或者sleep 1在写入之后添加myfifo,则会看到nl仅处理第一行或第一行快速行,则它会退出,因为看到了输入的末尾。

使用您的结构,您需要保持管道打开,直到不再需要它为止。您需要将单个输出重定向到管道中。

nl <myfifo &
exec 3>&1
while IFS= read -r line
do
  if [[ $line == @@inline-code-start* ]]
  then
    exec >myfifo
  elif [[ $line == @@inline-code-end* ]]
  then
    exec >&3
  else
    printf '%s\n' "$line"
  fi
done

(我也借此机会添加了正确的引号,例如-请参阅为什么我的shell脚本在空白或其他特殊字符上会感到窒息?

如果这样做,则不妨使用管道而不是命名管道。

while IFS= read -r line
do
  if [[ $line == @@inline-code-start* ]]
  then
    while IFS= read -r line && [[ $line != @@inline-code-end* ]] do
      printf '%s\n' "$line"
    done | nl
  else
    printf '%s\n' "$line"
  fi
done

您的awk解决方案真的很棒!我认为这是迄今为止最简洁(但仍很易读)的解决方案。awk是否可以保证将管道重复使用到nl的行为,还是可以awk决定:“嘿,您已经完成了足够的管道操作。我要关闭此管道并打开一个新管道”?您的“管道”解决方案也非常好。我本来不赞成使用嵌入式while循环的方法,因为我认为这可能会有些混乱,但是我认为您拥有的很棒。之前没有分号do。(我没有代表在这里做一些小的编辑。)
James Scriven 2015年

1
...我无法使您的命名管道解决方案正常工作。似乎存在竞争状况,因此,管道连接到nl的部分有时会完全丢失。另外,如果还有第二个@@ inline-code-start / end部分,它总是会丢失。
James Scriven 2015年

0

好,首先 我了解您不是在寻找一种对文件各部分中的行进行编号的方法。由于您尚未提供有关过滤条件的实际示例(除外nl),因此我们假设它是

tr "[[:lower:]]" "[[:upper:]]"

即,将文本转换为全部大写;因此,输入

line A
line B
@@inline-code-start
line X
line Y
line Z
@@inline-code-end
line C
line D

你想要一个输出

line A
line B
LINE X
LINE Y
LINE Z
line C
line D

这是我对解决方案的第一个近似值:

#!/bin/sh
> file0
> file1
active=0
nl -ba "$@" | while IFS= read -r line
do
        case "$line" in
            ([\ 0-9][\ 0-9][\ 0-9][\ 0-9][\ 0-9][\ 0-9]"        @@inline-code-start")
                active=1
                ;;
            ([\ 0-9][\ 0-9][\ 0-9][\ 0-9][\ 0-9][\ 0-9]"        @@inline-code-end")
                active=0
                ;;
            (*)
                printf "%s\n" "$line" >> file$active
        esac
done
(cat file0; tr "[[:lower:]]" "[[:upper:]]" < file1) | sort | sed 's/^[ 0-9]\{6\}        //'

@@字符串前面和最后一行结尾附近的空格是制表符。请注意,我nl 出于个人目的使用。(当然,我正在这样做是为了解决您的问题,而不是为了给您行号输出。)

这将对输入的行进行编号,以便我们可以在节标记处将其分开,并知道稍后如何再次将其组合在一起。循环的主体是基于您的首次尝试,并考虑到部分标记上带有行号的事实。它将输入分为两个文件:( file0不活动;不在一个节中)和file1(活动;一个节中)。对于上面的输入,它们是这样的:

file0:
     1  line A
     2  line B
     8  line C
     9  line D

file1:
     4  line X
     5  line Y
     6  line Z

然后,我们通过大写过滤器运行file1(这是所有横断面线的连接);将其与未过滤的异形线相结合;排序,以使其恢复原状;然后删除行号。这将产生输出,显示在我的答案顶部附近。

假设您的过滤器不留行号。如果没有(例如,如果它在行的开头插入或删除了字符),那么,我相信,仍然可以使用这种通用方法,但是需要稍微复杂一点的编码。


nl已经在那里完成了大部分工作-这就是其-delimiter选项的作用。
mikeserv 2015年

0

一个shell脚本,它使用sed输出未划界的行块并将已划界的行块馈入过滤器程序:

#!/bin/bash

usage(){
    echo "  usage: $0 <input file>"
}

# Check input file
if [ ! -f "$1" ]; then
    usage
    exit 1
fi

# Program to use for filtering
# e.g. FILTER='tr X -'
FILTER='./filter.sh'

# Generate arrays with starting/ending line numbers of demarcators
startposs=($(grep -n '^@@inline-code-start$' "$1" | cut -d: -f1))
endposs=($(grep -n '^@@inline-code-end$' "$1" | cut -d: -f1))

nums=${#startposs[*]}
nume=${#endposs[*]}

# Verify both line number arrays have the same number of elements
if (($nums != $nume)); then
    echo "Tag mismatch"
    exit 2
fi

lastline=1
i=0
while ((i < nums)); do
    # Exclude lines with code demarcators
    sprev=$((${startposs[$i]} - 1))
    snext=$((${startposs[$i]} + 1))
    eprev=$((${endposs[$i]} - 1))

    # Don't run this bit if the first demarcator is on the first line
    if ((sprev > 1)); then
        # Output lines leading up to start demarcator
        sed -n "${lastline},${sprev} p" "$1"
    fi

    # Filter lines between demarcators
    sed -n "${snext},${eprev} p" "$1" | $FILTER

    lastline=$((${endposs[$i]} + 1))
    let i++
done

# Output lines (if any) following last demarcator
sed -n "${lastline},$ p" "$1"

我将此脚本写入了一个名为detagger.sh的文件中,并按如下方式使用它:./detagger.sh infile.txt。我创建了一个单独的filter.sh文件来模拟问题中的过滤功能:

#!/bin/bash
awk '{ print "\t" NR " " $0}'

但是可以在代码中更改过滤操作。

我试图以此遵循通用解决方案的想法,以使诸如编号行之类的操作不需要额外的/内部的计数。该脚本进行了一些基本检查,以查看分界符标记是否成对,并且根本无法优雅地处理嵌套标记。


-1

感谢所有的好主意。通过跟踪临时文件中的小节并将其全部通过管道传递到我的外部命令,我提出了自己的解决方案。这与Supr建议的内容非常相似(但使用shell变量而不是temp文件)。另外,我真的很喜欢使用sed的想法,但是这种情况的语法对我来说似乎有点过头了。

我的解决方案:

(我nl仅用作示例过滤器)

#!/usr/bin/bash

while read line
do
  if [[ $line == @@inline-code-start* ]]
  then
    active=true
    tmpfile=$(mktemp)
    trap "rm -f $tmpfile" EXIT
  elif [[ $line == @@inline-code-end* ]]
  then
    active=false
    <$tmpfile nl
    rm $tmpfile
  elif [[ $active = true ]]
  then
    echo $line >> $tmpfile
  else
    echo $line
  fi
done

我希望不必处理临时文件,但我知道shell变量的大小限制可能非常小,而且我不知道会像临时文件一样工作的bash构造,但是当过程结束。


我想你希望能够为“累积状态跨线”,因此,例如,使用麦克风的测试数据,线MNO将被编号456。这不会那样做。我的回答是正确的(除了这样的事实,就目前而言,它不能nl用作过滤器)。如果答案正在为您提供所需的输出,那么“跨线累加状态”是什么意思?你的意思是你想不仅是为了维护国家通过每个部分,但不是之间(跨)部分?(为什么不将多部分的示例放入您的问题中?)
Scott

@Scott- nl -p用于获取M,N,O==4,5,6
mikeserv 2015年

我更新了问题以澄清我只对保持小节中的状态感兴趣,尽管我认为其他解释同样有趣。
James Scriven 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.