Bash 和 shell 扩展:惰性列表制作

2025-06-10

Bash 和 shell 扩展:惰性列表制作

又到了一年一度的节日季!商店开始摆放五彩缤纷、闪闪发光的塑料玩具,我们开始感受到节日的气氛。我说的“节日”是指去购物。确切地说,是去买节日礼物!(严格来说,给自己买的礼物也算礼物。)

为了不至于事与愿违,你应该列个礼物清单。Bash 可以帮到你。

括号扩展

这些不是大括号:()

这些都不是:[]

这些是大括号:{}

括号指示 Bash 对它们之间的任意字符串进行处理。多个字符串用逗号分隔:{a,b,c}。您还可以添加可选的序言和后记,将其附加到每个扩展结果中。通常,这可以节省一些输入,例如处理常见的文件路径和扩展名时。

让我们为每个想要赠送礼物的人列一些清单。以下命令是等效的:

touch /home/me/gift-lists/Amy.txt /home/me/gift-lists/Bryan.txt /home/me/gift-lists/Charlie.txt
touch /home/me/gift-lists/{Amy,Bryan,Charlie}.txt
tree gift-lists
/home/me/gift-lists
├── Amy.txt
├── Bryan.txt
└── Charlie.txt

哦,该死,“布莱恩”的名字拼写中有一个“i”。我可以解决这个问题。

mv /home/me/gift-lists/{Bryan,Brian}.txt

renamed '/home/me/gift-lists/Bryan.txt' -> '/home/me/gift-lists/Brian.txt'

Shell 参数扩展

Shell 参数扩展允许我们对括号中的参数进行各种更改,例如操作和替换文本。

有一些圣诞礼物是所有受赠者都应得的。我们将其设为变量:

STUFF=$'socks\nlump of coal\nwhite chocolate'
echo "$STUFF"

socks
lump of coal
white chocolate

现在,借助获取命令teeecho和扩展的帮助,将这些项目添加到我们的每个列表中,以便更好地发挥作用

echo "$STUFF" | tee {Amy,Brian,Charlie}.txt
cat {Amy,Brian,Charlie}.txt

socks
lump of coal
white chocolate
socks
lump of coal
white chocolate
socks
lump of coal
white chocolate

模式匹配替换

再想想,也许那块煤算不上什么好礼物。你可以用以下形式的模式匹配替换,把它替换成更好的东西${parameter/pattern/string}

echo "${STUFF/lump of coal/candy cane}" | tee {Amy,Brian,Charlie}.txt
cat {Amy,Brian,Charlie}.txt

socks
candy cane
white chocolate
socks
candy cane
white chocolate
socks
candy cane
white chocolate

这会将第一个“煤块”替换为“拐杖糖”。要替换所有实例(如果有多个),请使用${parameter//pattern/string}。这不会改变$STUFF变量,因此我们仍然可以将原始列表重新用于以后调皮捣蛋的人。

子字符串

在我们改进的过程中,受赠者可能并非都喜欢白巧克力。为了以防万一,我们最好在列表中添加一些普通巧克力。因为我超级懒,所以我打算点击向上箭头,修改之前的 Bash 命令。幸运的是,变量中的最后一个单词$STUFF是“chocolate”,它有九个字符长,所以我会告诉 Bash 使用 只保留这部分${parameter:offset}。我将使用标志将tee添加到我现有的列表中:-aa

echo "${STUFF: -9}" | tee -a {Amy,Brian,Charlie}.txt
cat {Amy,Brian,Charlie}.txt

socks
candy cane
white chocolate
chocolate
socks
candy cane
white chocolate
chocolate
socks
candy cane
white chocolate
chocolate

您还可以:

执行此操作 有了这个
获取从n 个字符开始的子字符串 ${parameter:n}
获取n开始的x 个字符的子字符串 ${parameter:n:x}

好了!现在我们的基础清单完成了。我们去喝点蛋酒吧。

测试变量

你知道,可能是蛋酒的问题,但我记得我昨天给艾米列了一个列表,并把它存进了一个名为 的变量里amy。我看看我是不是这么做了。我会用扩展。如果没有参数,${parameter:?word}它会写入标准错误并退出wordamy

echo "${amy:?no such}"

bash: amy: no such

我想不是。也许是布莱恩?

echo "${brian:?no such}"

Lederhosen

您还可以:

执行此操作 有了这个
word如果parameter未设置或为空,则替换 ${parameter:-word}
word如果parameter未设置或为空,则替换 ${parameter:+word}
如果未设置或为空,word赋值parameterparameter ${parameter:=word}

改变大小写

没错!Brian 说他想要一条皮短裤,所以我做了个记录。这很重要,所以我会用大写字母把它和${parameter^^pattern}扩展名一起添加到 Brian 的列表中。这pattern部分是可选的。我们只是写到 Brian 的列表中,所以我就用>>而不是tee -a

echo "${brian^^}" >> Brian.txt
cat Brian.txt

socks
candy cane
white chocolate
chocolate
LEDERHOSEN

您还可以:

执行此操作 有了这个
首字母大写 ${parameter^pattern}
将第一个字母小写 ${parameter,pattern}
全部字母小写 ${parameter,,pattern}

扩展数组

你知道吗,列礼物清单可是个大工程。我打算把在商店看到的东西列成一个系列:

gifts=(sweater gameboy wagon pillows chestnuts hairbrush)

我可以使用子字符串扩展来简化这个过程${parameter:offset:length}。我会将前两个添加到 Amy 的列表中,将中间两个添加到 Brian 的列表中,将后两个添加到 Charlie 的列表中。我将使用printf来帮助处理换行符。

printf '%s\n' "${gifts[@]:0:2}" >> Amy.txt
printf '%s\n' "${gifts[@]:2:2}" >> Brian.txt
printf '%s\n' "${gifts[@]: -2}" >> Charlie.txt
cat Amy.txt

socks
candy cane
white chocolate
chocolate
sweater
gameboy

cat Brian.txt

socks
candy cane
white chocolate
chocolate
LEDERHOSEN
wagon
pillows

cat Charlie.txt

socks
candy cane
white chocolate
chocolate
chestnuts
hairbrush

好了!现在我们有了一套完整的超级个性化礼物清单。谢谢 Bash!可惜它不能帮我们买东西。

鏂囩珷鏉ユ簮锛�https://dev.to/victoria/bash-and-shell-expansions-lazy-list-making-d74
PREV
自动化你的 GitHub 个人资料 README
NEXT
Unicode 替换密码算法