需要解释如何在 POSIX shell 中重复一个字符

Lin*_*eak 9 shell posix tr printf

Stack Overflow 上的以下答案,

如何在 bash 中重复一个字符?

强加了一种合理的POSIX方式-ly 重复单个字符,如下所示。在这个例子中,让我们使用等号 100 次:

printf %100s | tr " " "="
Run Code Online (Sandbox Code Playgroud)

我的问题是我不明白它是如何工作的,我更喜欢简单的解释。请不要像阅读手册那样发表评论,我这样做了,因为我不聪明,所以我问这个问题,因为我从未使用过tr,也没有见过这样的printf声明。

fil*_*den 14

简而言之,printf %100s将打印 100 个空格,tr " " "="并将这些空格转换为等号,从而有效地打印 100 个等号。

分解它:


printf是一个内置的shell。它通常需要两个或多个参数,第一个是“格式字符串”,其余的将用于填充该格式字符串中的占位符。一旦该模板完全填充,它将打印出结果。如果还有更多参数,它将重新开始,填充更多参数并打印结果字符串。

用于printf格式规范的格式字符串%以单个字母开头和结尾,因此%d表示整数(使用十进制基数,因此“d”),%f表示浮点数,%s表示字符串。之后的字符以外的字符%是格式规范的修饰符,特别是数字用于指定输出字段的请求长度。所以%100s会将字符串格式化为至少 100 个字符,它将用空格填充它并使其保持正确对齐(换句话说,在字符串的开头添加空格。)

如果传递了一个额外的参数,它将用于该%s字段,因此例如printf %100s abc将打印 97 个空格(总共 100 个,考虑到“abc”中的 3),然后是实际的字符串“abc”。但是如果没有给出参数,那么格式规范会填充一个空或空参数(对于 来说是一个空字符串,对于%s来说就是 0 %d,等等)所以这就像传递了一个空字符串一样,例如printf %100s ''. 最终结果是只打印了 100 个字符的填充。

所以,把它们放在一起,printf %100s结果打印了 100 个空格。


Nowtr是一种将字符从输入转换为输出的工具。它需要两个参数,SET1 和 SET2,每一个都是一组字符,然后将 SET1 的第一个字符转换为 SET2 的第一个字符,将 SET1 的第二个字符转换为 SET2 的第二个字符,依此类推。tr从 stdin 读取其输入并将其写回 stdout(因此它在像上面这样的管道中非常有用。)tr将始终翻译给定字符串中该字符的所有出现。

例如,tr aeiou 12345将按顺序将小写元音转换为数字 1 到 5,因此它将“排队”转换为“q52523ng”。您还可以传递字符范围,例如tr a-z A-Z将任何小写字母转换为其相应的大写字母。

因此tr " " "=",只需将整个字符串中的空格转换为等号即可。需要引用第一个空格才能将其识别为参数。在=实际上并不需要被引用,但这样做不会受到伤害。tr " " =会一样工作。


将它们放在一起,打印 100 个空格,然后将每个空格转换为等号。

希望这能足够详细地解释它,但如果您仍有不明白的地方,请发表评论,我会尽力解决。

  • @Vlastimil 实际上`printf '%100s' ''`,带有一个空字符串......我更新了答案以包含它。在这种特殊情况下,空字符串或单个空格不会有什么不同,但您可以在 `printf '%sx\n'` 中看到不同,它与 `printf '%sx\n' '' 相同` 但不同于 `printf '%sx\n' ' '`。我希望这有帮助! (2认同)

Mic*_*mer 11

printf命令使用其第一个参数作为打印其后续参数的格式printf %100s使用空格(在左侧)打印出填充到 100 个字符宽的参数。没有为 format 提供参数,因此它格式化空字符串一次,并输出 100 个空格。你可以看到:

$ printf %100s | hexdump -C
00000000  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
*
00000064
Run Code Online (Sandbox Code Playgroud)

(20 是空格的十六进制;*表示重复前一行)

格式字符串大约使用 CXprintf说明符:%、一个可选的宽度来适应格式化的值,以及要使用的格式类型。s是字符串格式,默认情况下,字符串左边用空格填充。可能有多种格式,或其他文字部分:printf "a%10sb\n" hello打印

 a         xb.
Run Code Online (Sandbox Code Playgroud)

tr用选定的替换替换其标准输入中的选定字符,并将结果打印到其标准输出。tr " " "="有一个要替换的字符 - 一个空格 - 和一个替换它的字符 - 一个等号。因此,它将其输入中的每个空格都变成了=,而其余​​的保持不变。你也可以试试:

$ tr " " "="
hello world
hello=world
Run Code Online (Sandbox Code Playgroud)

(我输入了“hello world”)

您可以有多个替换:tr abc def将 a 变为 d,将 b 变为 e,将 c 变为 f,其余部分保持不变。在这里它只是一个字符,因为它printf可以廉价地生成。

管道|导致左侧命令的输出 ,printf %100s用作右侧命令的输入tr " " "="。也就是说,给 100 个连续的空格tr,每个空格都被替换为=,并打印出新的字符串。

printf %100s | tr " " "="
====================================================================================================
Run Code Online (Sandbox Code Playgroud)