我对 UNIX (bash) 很陌生,一直在尝试使用该语言。我目前正在尝试从 .txt 文件创建一个具有固定标题的表。
所以我遇到了这样的代码:
column -t -s : <(echo Name:Age:Gender:Height:Weight) test.txt | sed "1{p;s/./*/g}"
sed
我对最后的命令部分完全感到困惑。我知道 the./*/g
的意思是用andsed
替换所有的意思是全局发生。.
*
/g
然而,the1
和 thep;s
实际上是什么意思呢?
答案1
这是一段相当聪明的代码。
塞德,正如您可以在优秀教程中学到的那样,适用于地址和命令。 如果省略地址,该命令将在每一行运行,例如常见的s/old/new/
.
地址可以是行号或正则表达式。或者它可以是逗号分隔的地址范围,我不会进一步描述。 (有关详细信息,请参阅上面链接的教程。)
命令可以是单个命令,也可以是花括号中包含的多个命令。
此 sed 命令运行p
rint 命令进而s
输入第 1 行的 ubstitute 命令。结果是在第一行输入之后会出现一个***
相同长度的字符串。
您可能会注意到该s
命令后面没有任何p
rint 命令,但在每行的末尾,“模式空间”中保存的任何内容都会隐式打印,除非该-n
选项首先传递给 sed。 (再次,请参阅上面链接的教程以了解更多信息。)
从本质上讲,这是为表格制作漂亮标题的快速方法。
编辑回答评论:
因此该
p
命令可以放置在 1sed 开头的任何位置or at the end? Also, the
。`(句点)意味着地址被省略?
不,不完全是。
也就是说1
,仅在输入的第一行应用以下命令列表(括在大括号内)。
其p
含义是,打印模式空间的当前内容,后跟换行符。 (此时模式空间将包含第一行输入,因为这就是 Sed 的工作方式。)
这s/./*/g
意味着,对于g
正则表达式.
(匹配任何字符)的每个匹配(全局),替换字符*
。这在模式空间上进行操作。
然后在命令末尾(右花括号),由于没有更多命令,因此隐式打印模式空间的内容。此时它仅包含一堆星号 ( ***
)。
然后下一行输入被读入模式空间。由于地址1
不匹配,因此将跳过大括号命令块。在大括号块的末尾,由于没有更多命令,因此隐式打印模式空间的内容。只要有输入就重复这一段。所以结果是第一行之后的其余输入被打印,没有改变。
因此,输出将包含输入的所有行,加上第一行之后的一行,该行仅由字符组成*
,并且与第一行的长度相同。
答案2
*
sed 脚本打印输入的第一行,然后打印与第一行宽度完全相同的一行字符。
1{p;s/./*/g}
1
是仅与输入的第一行匹配的地址。即块sed
中的命令{}
仅适用于第一行。p
- 打印输入而不改变;
是命令分隔符,在本例中分隔p
命令和s/./*/g
命令。s/./*/g
- 将每个字符更改为 a*
,并打印结果。
sed
任何剩余的输入(第 2+ 行)如果按照 的默认行为存在(如果在没有该-n
选项的情况下使用),则将不加修改地打印出来
整个命令:
column -t -s : <(echo Name:Age:Gender:Height:Weight) test.txt | sed "1{p;s/./*/g}"
用于column -t -s :
将由回显字符串"Name:Age:Gender:Height:Weight"
和 的内容组成的输入制成表格file.txt
。 column
的输出通过管道传输以sed
生成 s 行,******
将标头与输出的其余部分分开。