在bash中每个字母定义变量的回声不同
问题描述:
我的队友之前在unix SE上问过这个问题,但他问的是错误的。他也没有得到正确的答案。在bash中每个字母定义变量的回声不同
无论如何,我试图让我的bash脚本处理变量中的每个字符,并且每个字母都回显特定的字符串,直到达到最后。这是我到目前为止有:
#!/bin/bash
echo Word?
read -r -p '' foo
# $foo is set to 'Mammals and Bricks' by user.
wordlength=${#foo}
$wordlength says 18, so start on character 1.
'M' is first letter received in $foo, so echo '{m,M}'
'a' is second letter received in $foo, so echo '{a,A}'
'm' is third letter received in $foo, so echo '{m,M}'
'm' is fourth letter received in $foo, so echo '{m,M}'
'a' is the fifth letter received in $foo, so echo '{a,A}'
'l' is the sixth letter received in $foo, so echo '{l,L}'
's' is the seventh letter received in foo, so echo '{s,S}'
' ' is the eighth, so echo '\ '
........
'c' is sixteenth letter received in $foo, so echo '{c,C}'
'k' is seventeenth letter received in $foo, so echo '{k,K}'
's' is eighteenth letter received in $foo, so echo '{s,S}'
这里是它会是什么样子对用户端:
Word?
哺乳动物和砖
{m,M}{a,A}{m,M}{m,M}{a,A}{l,L}{s,S} {a,A}{n,N}{d,D} {b,B}{r,R}{i,I}{c,C}{k,K}{s,S}
哪个会是什么输出恰好为。你会看到所有上面的原始字符。
任何人都知道如何做到这一点?
答
开始通过在字符串中的字符循环:
foo=string
for ((i=0; i<${#foo}; i++)); do
echo "${foo:$i:1}"
done
(参考:How to perform a for loop on each character in a string in BASH?)
现在用case语句替换回声声明:
foo=string
for ((i=0; i<${#foo}; i++)); do
case "${foo:$i:1}" in
a)
echo "Do something with a here";
;;
[bB])
echo "Do something with b or B here";
;;
esac
done
答
下面是一个解决方案与GNU sed
,如果你不介意使用它:
sed 's/[a-zA-Z]/{\l&,\u&}/g' <<< "$foo"
\l
和\u
是GNU扩展到sed
,分别将下一个字符转为小写和大写。
[编辑]这里是bash
一个解决方案,因为你没有GNU sed
:
while read -r -n1; do
if [[ "${REPLY^}" == [A-Z] ]]; then
printf '{%c,%c}' "${REPLY,}" "${REPLY^}"
else
printf '%c' "$REPLY"
fi
done <<< "$foo"
echo
[编辑]附:不幸的是,这在OS X Yosemite上不起作用,因为$ {var,}和$ {var ^}结构是在bash v4中添加的,但是MacOS仅随bash v3.2.57一起发布(这是因为bash v4在GPL v3,Apple不想遵守)。感谢@GordonDavisson为此添加。
因此,这里是应该与你的bash
v3上运行的解决方案:
printf '%s\n' "$foo" \
| while read -d '' -r -n1; do
lowercase="$(printf '%c' "$REPLY" | tr '[:upper:]' '[:lower:]')"
uppercase="$(printf '%c' "$REPLY" | tr '[:lower:]' '[:upper:]')"
if [ "$lowercase" != "$uppercase" ]; then
printf '{%c,%c}' "$lowercase" "$uppercase"
else
printf '%c' "$REPLY"
fi
done
嗯......当我跑我的输出是这样的:'{LM,UM} {LA,UA} {LM ,um} {lm,um} {la,ua} {ll,ul} {ls,us} {la,ua} {ln,un} {ld,ud} {lB,uB} {lr,ur} {li ,UI} {LC,UC} {LK,英国} {LS,我们}'。我使用OS X Yosemite btw – leetbacoon
然后你可能使用的是经典的sed,而不是GNU sed(注意GNU sed可能在OSX上可用)。我在纯bash中添加了一个解决方案。 – xhienne
@xhienne不幸的是,'$ {var,}'和'$ {var ^}'构造是在bash v4中添加的,但是macOS只随bash v3.2.57一起发布。 (这是因为bash v4是根据GPL v3获得许可的,苹果不想遵守。) –