使用常见的 bash 工具作为 shell 脚本的一部分,我想以每 N 个字符的间隔重复将换行符 ('\n') 插入到长字符串中。
例如,给定这个字符串,我如何每 20 个字符插入一个换行符?
head -n 50 /dev/urandom | tr -dc A-Za-z0-9
我试图实现的结果示例:
ZL1WEV72TTO0S83LP2I2
MTQ8DEIU3GSSYJOI9CFE
6GEPWUPCBBHLWNA4M28D
P2DHDI1L2JQIZJL0ACFV
UDYEK7HN7HQY4E2U6VFC
RH68ZZJGMSSC5YLHO0KZ
94LMELDIN1BAXQKTNSMH
0DXLM7B5966UEFGZENLZ
4917Y741L2WRTG5ACFGQ
GRVDVT3CYOLYKNT2ZYUJ
EAVN1EY4O161VTW1P3OY
Q17T24S7S9BDG1RMKGBX
WOZSI4D35U81P68NF5SB
HH7AOYHV2TWQP27A40QC
QW5N4JDK5001EAQXF41N
FKH3Q5GOQZ54HZG2FFZS
Q89KGMQZ46YBW3GVROYH
AIBOU8NFM39RYP1XBLQM
YLG8SSIW6J6XG6UJEKXO
一个用例是快速生成一组固定长度的随机密码或 ID。我上面例子的做法是:
for i in {1..30}; do head /dev/random | tr -dc A-Z0-9 | head -c 20 ; echo ''; done
但是,出于学习目的,我想以不同的方式进行。我想从任意长的字符串开始并插入换行符,从而将一个字符串分成多个固定字符长度的小字符串。
答案1
尊者fold
命令(“由 Bill Joy 于 1977 年 6 月 28 日编写”)可以换行:
$ printf "foobarzot\n" | fold -w 3
foo
bar
zot
然而,也有一些边缘情况
错误 传统的 roff(7) 输出语义由 GNU nroff 和 mandoc(1) 实现,仅使用单个退格键来备份前一个字符,即使对于双角字符也是如此。 POSIX 所需的折叠退格语义错误地处理了此类退格编码序列,导致过早断行。 fmt(1) 实用程序提供类似的功能,并且不会遇到该问题,但未由 POSIX 标准化。
因此,如果您的输入包含退格字符,您可能需要过滤或删除这些字符
$ printf "a\bc\bd\be\n" | col -b | fold -w 1
e
$ printf "a\bc\bd\be\n" | tr -d "\b" | fold -w 1
a
c
d
e
答案2
我喜欢这个fold
答案,但以防万一你想要sed
,这里是:
sed 's/.\{20\}/&\
/g' filename
您可以用于-i
就地插入。
答案3
如果变量中有内容,例如:
var=$(head -n 50 /dev/urandom | tr -dc A-Za-z0-9)
然后,您可以在变量的长度上使用 bash 循环(以 20 块为单位),打印出每个块:
for((start=1;start < ${#var}; start += 20)); do printf '%s\n' "${var:start:20}"; done
如果您希望它们作为单独的变量,请考虑将输出分配给数组:
readarray -t passwords < <(for((start=1;start < ${#var}; start += 20)); do printf '%s\n' "${var:start:20}"; done)
答案4
我不会这样做来tr -dc
摆脱不可打印的字符,而是只使用base64
coreutils 中的内容:
$ base64 -w20 /dev/urandom | head -8
ckXkWvb0zJknz2zi4fRS
3Jv0dDbKiX8fef7SOfbH
QJySlGUzzhi32wvrGliK
YEiuz6v+EFaRYRMjvnJq
HCXIPiP9wmgONLRqm9uK
iHYwo5xIs8gGjQQEQBeX
8NkL4EkmOAHdmWhGvZYl
AcxD2DaTq2TZRsDL+UMx
如果+
和/
出现问题,您可以更换它们:
$ base64 -w20 /dev/urandom | tr +/ pq | head -8
zr7MgiEr7xBd7h9ihK30
IRNvDuT2H9HsHVq9yFqh
S1cihgfAInjfFspMNXVC
qUUwGErD7nZqtzQtLOo7
DNDp4TVWvHmbEh7HLDGX
GtqqDdEoceY8m5U7FGu0
TvGtTukm6Whr7VHN1mZG
DW5TUH525IA52zLKYACV