传递给“sed -e”的这个脚本的功能是什么?

传递给“sed -e”的这个脚本的功能是什么?

TL;DR- 下面的模式中发生了很多事情sed,我不确定如何将离散的部分组合成一个整体命令。


重击版本:GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin21)

我正在通过逐个文件阅读 RBENV 代码库来学习 shell 脚本,并且我遇到过该rbenv-help文件,其中包括这个函数定义

extract_initial_comment_block() {
  sed -ne "
    /^#/ !{
      q
    }

    s/^#$/# /

    /^# / {
      s/^# //
      p
    }
  "
}

我明白这个函数是如何调用的在代码的下面,所以我知道它的第一个参数是一个文件名:

extract_initial_comment_block < "$filename" | collect_documentation

从这里我可以看到由“$filename”表示的文件被作为命令的标准输入sed。就我的问题而言,连锁函数“collect_documentation”是无关紧要的。

我还从函数的名称中得知,它的目的是获取类似的文件,并返回其摘要和使用注释,即链接文件的第 2-14 行。然而,我还没有测试过这个理论,所以我可能不是100%正确的。

此外,我知道来自这个 StackExchange 答案该标志的目的-e是告诉sed将后续字符串解释为命令(或由换行符分隔的命令集合?)。所以看起来主体extract_initial_comment_block包含 3 个单独的脚本,用于sed按顺序进行解释。同一个 StackExchange 答案说用于{...}将命令分组在一起,但我不确定这是否是这个正则表达式(这些正则表达式?)中发生的情况。

据我所知,sed这里有 3 个脚本:

    /^#/ !{
      q
    }
    s/^#$/# /
    /^# / {
      s/^# //
      p
    }

然而,即使在每个脚本中,也存在一些我无法识别的正在使用的模式(例如^#和),即使在利用了诸如!{ q }Linux 数据项目。看起来有很多动人的部分,我不确定每个脚本是如何组合成成品的。

我尝试尽可能清晰地阐述我的思考过程。到目前为止我的思路正确吗?如果不是,我哪里偏离了方向?如果是,我如何推断传递给的每个命令的含义sed

答案1

/^#/ !{
      q
    }

斜杠之间的部分是正则表达式,其中^表示字符串的开头,#只是字符本身。该模式选择运行关联命令的行。尾随!反转了匹配的含义,q是退出的命令。因此,当 sed 程序看到一行时,它会退出从评论标记开始#

 s/^#$/# /

s/a/b/ s用 b 代替 a,^是行首,$是行尾,#是它本身。因此,这将仅用一个单独的线更改##+空格。

/^# / {
  s/^# //
  p
}

#如果该行以 a和空格 ( /^# /)开头,则将#和 空格替换为空 ( s/^# //) 并打印该行 ( p)。这就是之前的替换派上用场的地方。

sed 的选项-n(在命令开头)告诉 sed不是在执行脚本后打印该行,就像默认情况下一样。

请注意,该脚本会忽略以 a#和开头的行之后有一个空格,包括以该空格开头的 hashbang 行,#!告诉操作系统该脚本使用哪个解释器。可能是故意的,但可能隐藏一些其他线路。

例如

#!/bin/sh
# some script
#
#this is ignored
# this prints

# this doesn't print any more
whatever

变成

some script

this prints

相关内容