我有一个输入文件,其中的某些部分用开始和结束标记来分隔,例如:
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
作示例过滤器。我以为可以通过掩盖过滤器确切执行的详细信息来简化问题,但我可能只会引起更多的混乱。实际上,我正在通过代码突出显示过滤该部分,以用于本地静态博客生成器。现在,我正在使用gnu source-highlight
,但这可能会改变,并且我可能会添加更多过滤器,例如格式化程序。
nl
不必积累状态。看nl -d
,并检查您man
/info
关于信息页面nl
的部分分隔符。