【发布时间】:2020-05-09 20:24:25
【问题描述】:
我正在阅读/编辑一个 bash git 集成脚本
这个 sn-p 应该打印 ${SYMBOL_GIT_PUSH} 或 ${SYMBOL_GIT_PULL} 以及我落后和/或领先的提交数。
local marks
while IFS= read -r line; do
if [[ $line =~ ^## ]]; then
[[ $line =~ ahead\ ([0-9]+) ]] && marks+=" ${BASH_REMATCH[1]}${SYMBOL_GIT_PUSH}"
[[ $line =~ behind\ ([0-9]+) ]] && marks+=" ${BASH_REMATCH[1]}${SYMBOL_GIT_PULL}"
else
marks="${SYMBOL_GIT_MODIFIED}${marks}"
break
fi
done < <(git status --porcelain --branch 2>/dev/null)
printf '%s' "$marks"
例子:
4↑ 10↓
它正在工作,但我正在努力理解它。
为什么会有一些IFS 以及它如何与进程替换一起工作?
我听说sh 中没有定义流程。有没有办法以/bin/sh 方式或至少更有效地做到这一点?
我得到了a link,它应该可以解释IFS 的作用。
我切换了混淆的东西并设法删除了进程替换:
local marks
git status --porcelain --branch 2>/dev/null |
while IFS= read -r line; do
if [[ $line =~ ^## ]]; then
[[ $line =~ ahead\ ([0-9]+) ]] && marks+=" ${BASH_REMATCH[1]}${SYMBOL_GIT_PUSH}"
[[ $line =~ behind\ ([0-9]+) ]] && marks+=" ${BASH_REMATCH[1]}${SYMBOL_GIT_PULL}"
else
marks="${SYMBOL_GIT_MODIFIED}${marks}"
break
fi
done
printf '%s\n' "$marks"
但是现在,$marks 的值没有保存,它什么也不打印。
我收到了another link,这解释了原因。
将返回并更新我的发现。
我使用命令分组解决方法并将循环和打印语句包裹在花括号内:
此外,我使 /bin/sh 版本几乎可以正常工作(例外 - 显示我领先或落后的提交量,不难,我相信我会用 awk 或 cut 做一些事情)。
我利用了 grep 在没有匹配项时返回非 0 的事实。
git status --porcelain --branch 2>/dev/null | {
SYMBOL_GIT_PUSH='↑'
SYMBOL_GIT_PULL='↓'
while IFS= read -r line
do
if echo "$line" | egrep -q '^##'
then
echo "$line" | egrep -q 'ahead' && marks="$marks $SYMBOL_GIT_PUSH"
echo "$line" | egrep -q 'behind' && marks="$marks $SYMBOL_GIT_PULL"
else
marks="*$marks"
break
fi
done
printf ' %s' "$marks"
}
这是一次有趣的学习经历!感谢所有帮助过的人。当我找到 100% 的解决方案时,我会更新它。
【问题讨论】:
-
那么什么不起作用?你想改进什么?
-
将您的代码放入脚本中,并将
#!/bin/sh添加为shebang,然后将其粘贴到shellcheck.net,这应该会给您一些帮助。sh也没有正则表达式,只有 glob,但如果你真的需要正则表达式,那么你需要使用外部实用程序,如grep、sed或awk和朋友。 -
关于进程替换,当它与重定向结合时 - 就像在你的例子中一样 -
command … < <(command2 …)可以用一个简单的管道重写,command2 … | command … -
要了解
IFS的含义,请参阅:mywiki.wooledge.org/IFS -
用管道替换有一个重要的区别:命令在子shell中运行,请参阅BashFAQ/024。对于问题中的示例,
marks最后会为空,所以这里肯定不等价。