需要如何在POSIX Shell中重复字符的说明


8

关于堆栈溢出的以下答案,

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

强制采用一种可能的POSIX方式- 重复单个字符,如下所示。在此示例中,我们使用等号100次:

printf %100s | tr " " "="

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

Answers:


13

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

分解:


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

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

如果传递了一个额外的参数,它将在该%s字段中使用它,例如,printf %100s abc将打印97个空格(考虑到“ abc”中的3个,总共打印100个空格),后跟实际的字符串“ abc”。但是,如果未提供任何参数,则格式说明将填充一个空或null参数(对于%s,它是一个空字符串,对于等,它将为0 %d)。这就像传递了一个空字符串一样,例如printf %100s ''。最终结果是仅打印100个字符的填充。

因此,将所有内容放在一起,printf %100s可以打印100个空格。


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

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

所以,tr " " "="简单地翻译成空格整个字符串等号。需要引号中的第一个空格以将其识别为参数。在=实际上并不需要被引用,但这样做不会受到伤害。tr " " =本来可以一样的。


将所有内容放在一起,打印100个空格,然后将每个空格翻译成等号。

希望这能对它进行足够详细的解释,但是如果您仍然不了解某些内容,请发表评论,我将尝试解决。


仅检查一下,以下内容在语法上是否更正确?:printf '%100s' ' ' | tr " " "="
LinuxSecurityFreak

2
@Vlastimil实际上printf '%100s' '',使用空字符串...我更新了答案以包括该内容。在这种特殊情况下,空字符串或单个空格不会有什么区别,但是您可以看到的区别printf '%sx\n',这与相同,printf '%sx\n' ''但有所不同printf '%sx\n' ' '。希望对您有所帮助!
filbranden

1
提及+1可以tr对字符集进行操作。这经常被遗漏。
Sergiy Kolodyazhnyy

11

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

$ printf %100s | hexdump -C
00000000  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
*
00000064

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

格式字符串大约使用C的Xprintf说明符:%,可选的宽度(适合格式的值)和要使用的格式类型。s是字符串格式,默认情况下在字符串的左侧用空格填充。可能有多种格式,或其他文字部分:printf "a%10sb\n" hello版画

 a         xb.

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

$ tr " " "="
hello world
hello=world

(我输入了“ hello world”)

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

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

printf %100s | tr " " "="
====================================================================================================

仅检查一下,以下内容在语法上是否更正确?:printf '%100s' ' ' | tr " " "="
LinuxSecurityFreak

1
格式化空格并用空格填充将提供与格式化空字符串并用空格填充相同的输出,但是在结构上并不等效。就所发生的事情的清晰度而言,也许更“正确”,但在语法上却不正确,因为它们是不同的命令。
迈克尔·荷马
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.