鉴于以下ed
脚本,
$ cat helloworld
a
hello
world
.
,n
,s,o,O,g
,n
Q
我想以某种方式获得交互式输出
$ ed
a
hello
world
.
,n
1 hello
2 world
,s,o,O,g
,n
1 hellO
2 wOrld
Q
$
而不是预期的
$ cat helloworld | ed
1 hello
2 world
1 hellO
2 wOrld
$
这可能吗,也许使用第三方实用程序?提前致谢!
编辑:我想我应该增加一些动力。我想制作一些示例编辑会话,并可能将它们保存为script(1)
.如果这个过程是“实时”执行的,任何修改基本上都意味着再次输入整个教程(不好),或者“弄清楚”输出,可能基于长时间的编辑会话(更糟糕)。
答案1
好吧,在胡闹之后,这就是我要使用的:
awk '{ print; system("sleep 0") }' edscript | tee /dev/tty | ed
或者,没有tee
:
awk '{ print >"/dev/stderr"; print | "ed"; system("sleep 0") }' edscript
如果print >"/dev/stderr"
在您的系统上不起作用,您可以使用print | "cat >&2"
.
和gnu sed
:
sed -u -n -e 'p;w /dev/stderr' -e 's|.*||e' edscript | ed
另一种同样有效的方法:
使用split
来分割你的编辑脚本每行:
split -l1 edscript
这将产生类似xaa
,xab
...的作品xah
。
然后你可以像这样使用这些部分:
for i in x*; do awk '{ print >"/dev/stderr"; print }' $i; done | ed
或者
for i in x*; do sed -n -e 'p;w /dev/stderr' $i; done | ed
以获得预期的结果。然后你rm x*
...
答案2
听起来您想模拟一个交互式终端会话,其中用户键入命令,等待响应(或者,假设目标是ed
,有时等待响应),然后键入另一个命令等。您可以编写一个expect
脚本来执行此操作,但一次只向终端和目标进程发送一行可能就足够了,中间有短暂的停顿每行。
$ while IFS= read -r line
do
printf '%s\n' "$line" >/dev/tty
printf '%s\n' "$line"
sleep 0.5
done < helloworld | ed
a
hello
world
.
,n
1 hello
2 world
,s,o,O,g
,n
1 hellO
2 wOrld
Q
为了更好地区分输入和输出,您可以向该行添加颜色或其他突出显示,或者在这种特殊情况下,启用(命令)echo "$line" >/dev/tty
中的提示字符,以便 a将显示在每个命令的前面。ed
P
*
ed
答案3
我做了一些……复杂的事情。我最近一直在研究ex
/ ed
- 我对两者都不太擅长 - 这标志着一个更深入研究的机会。首先解析ed
脚本并将其传递到ed
流内:
b='[:blank:]'
sed -e 'h;/\n/!i\' -e 0i -e 's/^\(.*[^\]\)*\(\\\\\)*\\$//;tn'"
/^\n*\([0-9;$,.$b]*[gGvV].*\\\\\n[$b]*\)*\([0-9,$.;${b}]*[aic][$b]*\)\
\(\n\(.*\)\n\.\)*\(\n.*\)*$/{ s//\4/;:n" -e 'G;//{N;D
};g;s//\1\2/;l;x;s//\4/;l;H;s/.*/./;a\' -e '.
};l;g;i\' -e .\\ -e 1,.p\\ -e u <ed_script | ed
它没有以前那么复杂 - 现在几乎所有的复杂性都集中在跨越两行的单个正则表达式中。这一长长的正则表达式几乎处理整个脚本的所有测试。
据我所知,这个想法是,你只能到达插入a
模式与pend、i
nsert 或之一c
hange 命令插入然后,模式将所有输入字面地接受到下一个仅由.
点组成的行。任何其他跨越多行的连续命令 - 即使涉及G
、g
、V
或的序列v
- 都必须继续到带有尾随\
反斜杠的下一行 - 尽管像往常一样,\
反斜杠在该上下文中会自行转义。
所以,虽然我完全有可能错了,但我思考这可以处理所有情况。对于与[aic]
... .
点系列不匹配的每个输入行,sed
插入一系列如下所示的命令:
0i
command-line$
.
1,.p
u
...指示ed
插入i
明确的l
ook(如所写sed
)按照它自己的命令,然后p
打印它,最后到u
完成整个操作 - 这具有完成编辑、打印它、反转它的非常方便的结果,和通过单个操作恢复最后一个地址。
对于那些符合以下条件的人做匹配尾随反斜杠的序列或[aic]
....
系列,这有点复杂。在这些情况下,sed
会递归地将它们拉入,直到遇到该系列的末尾,然后再执行l
操作。我小心地将[aic]
、.
和 实际文字输入分成单独的打印 - 每个类型都会有自己的l
ook - 以便文字输入尽可能地串在一起(默认情况下sed
将在 80 个字符处中断l
ook 输出)。
我想向您展示会更容易。您会注意到?
下面的提示 - 发生这种情况是因为g
之前给出的命令不是有效命令 - 不是因为sed
破坏了输入(我希望)。以下是示例数据集的修改版本的输出:
g \\\n a$
hello\nworld\\\n\n 0a\n world\\\nworld\nworld$
.$
?
,n$
1 hello
2 world\
3
4 0a
5 world\
6 world
7 world
,s,o,O,g$
4$
0a
.,$n$
4 0a
5 wOrld\
6 wOrld
7 wOrld
,s,$,\\\n\\\n\\\\$
\
,n$
1 hellO
2
3 \
4 wOrld\
5
6 \
7
8
9 \
10 0a
11
12 \
13 wOrld\
14
15 \
16 wOrld
17
18 \
19 wOrld
20
21 \
Q$