gpt4 book ai didi

algorithm - 这个 sed 程序是如何工作的?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:16:37 25 4
gpt4 key购买 nike

我在 Stackoverflow 上的其他地方的评论中发现了这个 sed 程序,用于打印文件的最后 5 行以外的所有行,我已经分解并逐行评论:

删除-last-5.sed

# create a label "a"
:a

# - on the last line, delete the pattern space and skip any remaining commands
$d

# - increment the current line number
# - append the current line (which was previously the next line)
# to the pattern space
N

# - on lines 2-5, branch to label "a"
2,5ba

# - print the first line of the pattern space
P

# - delete the first line of the pattern space
# - skip any remaining commands
# - if any text remains in the pattern space, when the next line is read,
# append to (rather than overwrite) the pattern space
D

一个例子是:

$ echo a b c d e f g h i j | xargs -n1 | sed -f delete-last-5.sed
a
b
c
d
e

但是,我实际上无法弄清楚它是如何工作的!据我所知,程序执行是这样的:

- _: line_number = 1
- _: pattern_space = "a"
- N: pattern_space += "\nb", line_number = 2
- 2,5ba: branch to label "a"
- N: pattern_space += "\nc", line_number = 3
- 2,5ba: branch to label "a"
- N: pattern_space += "\nd", line_number = 4
- 2,5ba: branch to label "a"
- N: pattern_space += "\ne", line_number = 5
- 2,5ba: branch to label "a"

- N: pattern_space += "\nf", line_number = 6
- P: print "a"
- D: pattern_space -= "a\n"
- _: pattern space is not empty after D, so mark pattern space to be appended to rather than overwritten

- _: line_number = 7
- _: pattern_space += "\ng"
- P: print "b"
- D: pattern_space -= "b\n"
- _: pattern space is not empty after D, so mark pattern space to be appended to rather than overwritten

- _: line_number = 8
- _: pattern_space += "\nh"
- P: print "c"
- D: pattern_space -= "c\n"
- _: pattern space is not empty after D, so mark pattern space to be appended to rather than overwritten

- _: line_number = 9
- _: pattern_space += "\ni"
- P: print "d"
- D: pattern_space -= "d\n"
- _: pattern space is not empty after D, so mark pattern space to be appended to rather than overwritten

- _: line_number = 10
- _: pattern_space += "\nj"
- $d: delete pattern_space

如果你收集所有这些打印语句,你最终会得到:

a
b
c
d

缺少第 5 行。

如何打印最后一行?我对这个程序的解释哪里出错了?

最佳答案

Sed 调试可能有点痛苦。有有限的内置选项可以帮助您:l命令打印带有不可见字符的当前模式空间,例如打印换行符、制表符和行尾,以及 = (GNU 扩展)打印当前行号。

将这些与您的示例输入一起使用,在 N 之前和之后打印行号和当前模式空间命令给了我们这个:

$ sed ':a;$d;=;l;N;=;l;2,5ba;P;D' <<< "$(printf 'a\nb\nc\nd\ne\nf\ng\nh\ni\nj\n')"
1
a$
2
a\nb$
2
a\nb$
3
a\nb\nc$
3
a\nb\nc$
4
a\nb\nc\nd$
4
a\nb\nc\nd$
5
a\nb\nc\nd\ne$
5
a\nb\nc\nd\ne$
6
a\nb\nc\nd\ne\nf$
a
6
b\nc\nd\ne\nf$
7
b\nc\nd\ne\nf\ng$
b
...
<snip>
...
d
9
e\nf\ng\nh\ni$
10
e\nf\ng\nh\ni\nj$
e

查看 <snip> 之后的部分, 我们刚刚打印了 d , 和 D命令没有读取新行就把我们送回了循环的开始。我们正在查看第 9 行,其中包含 i (已经在我们的模式空间的末尾)。

现在我们通过命令:

  • $d – 忽略,我们正在查看第 9 行,这不是最后一行(参见调试输出)
  • N – 附加第 10 行;调试输出显示 j已附加,我们实际上正在查看第 10 行
  • 2,5ba – 忽略,我们已经过了第 5 行
  • P – 打印第一行:这是 e 的位置来自
  • D – 删除第一行,重新开始循环,不读下一行

下一个周期:

  • $d现在我们正在看最后一行。删除模式空间,不打印任何内容,我们完成了!

我认为您分析中的错误是您在新周期开始时增加了行号,但唯一增加行号的地方是 N。命令。 (顺便说一句,你忘了在最后几行中提到这一点。)

如果您想更深入地研究 sed 脚本,可以使用 sed 调试器:sedsed ,用 Python 编写。命令最后两行的输出如下所示:

PATT:e\nf\ng\nh\ni$
HOLD:$
COMM::a
COMM:$ d
PATT:e\nf\ng\nh\ni$
HOLD:$
COMM:N
PATT:e\nf\ng\nh\ni\nj$
HOLD:$
COMM:2,5 b a
COMM:P
e
PATT:e\nf\ng\nh\ni\nj$
HOLD:$
COMM:D
PATT:f\ng\nh\ni\nj$
HOLD:$
COMM::a
COMM:$ d

它显示每个命令的保持和模式空间。

该示例(10 行而不是 5 行)是在 Peteris Krumins' site 上解释的 100 个 sed 单行代码之一。 (示例 75),但解释不是很详细。相同的原理可以在 Eric Pement 的 sed one-liners 中找到。 (这是“单行解释”的灵感来源)。

关于algorithm - 这个 sed 程序是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41080428/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com