我想修改我最近的一个Bash别名来转发错误。这是别名:
alias makecclip=
"make |& tee >(sed \"s,\x1B\[[0-9;]*[a-zA-Z],,g\" |
egrep \":[0-9]+:[0-9]+: error\" | cut -d : -f1,2,3 |
head -n 1 | xargs -0 echo -n | xclip -selection clipboard &&
xclip -selection clipboard -o)
此代码显示C ++编译的结果,然后删除格式和显示,并将第一个错误位置(如果有)添加到剪贴板。
但是,我想使用这样的代码:
makecclip && bin/someexecutablecreated
这虽然破坏了&&
运算符,因为它总是运行bin / someexecutablecreated,即使存在编译错误也是如此。当错误列表(保存到剪贴板并回显的内容)不为空时,如何添加对代码的修改以设置错误标志?
答案 0 :(得分:1)
您可以使用PIPESTATUS
内部变量(此变量在非bash shell中具有其他名称)来解决您的问题。这允许具有管道传递的命令的退出状态的历史记录。
您在评论中对未使用bash
进行了预测,但使用了zsh
。因此,我的解决方案的一些语法必须改变,因为它们以不同的方式处理PIPESTATUS
变量。
在bash中,您使用${PIPESTATUS[0]}
,而在zsh中使用${pipestatus[1]}
。
使用现有别名的第一种方法可以如下:
makecclip && [ "${pipestatus[1]}" -eq "0" ] && echo "ok"
仅当echo
等于0(make期间没有错误)时才会运行"${pipestatus[1]}"
命令
更方便的解决方案是使用函数而不是makecclip
的别名。在~/.bashrc
文件中,您可以写:
makecclip () {
make |& tee >(sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" | egrep ":[0-9]+:[0-9]+: error" | cut -d : -f1,2,3 | head -n 1 | xargs -0 echo -n | xclip -selection clipboard && xclip -selection clipboard -o)
return "${pipestatus[1]}"
}
现在,makecclip && echo "ok"
将按预期工作。
测试用例:
#!/bin/zsh
#do not run this test if there is an existing makefile in your current directory
rm -f makefile
makecclip () {
make |& tee >(sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" | egrep ":[0-9]+:[0-9]+: error" | cut -d : -f1,2,3 | head -n 1 | xargs -0 echo -n | xclip -selection clipboard && xclip -selection clipboard -o)
# this part is only present to check the pipestatus values during the tests.
# In the real function, I wrote 'return ${pipestatus[1]}' instead.
a=(${pipestatus[@]})
echo ${a[@]}
return ${a[1]}
}
echo "# no makefile"
makecclip && echo "ok"
echo -e "\n# empty makefile"
touch makefile
makecclip && echo "ok"
echo -e "\n# dummy makefile entry"
echo -e 'a:\n\t@echo "inside makefile"' > makefile
makecclip && echo "ok"
echo -e "\n# program with error makefile"
echo -e "int main(){error; return 0;}" > target.cc
echo -e 'a:\n\tgcc target.cc' > makefile
makecclip && echo "ok"
输出:
$ ./test.sh
# no makefile
make: *** No targets specified and no makefile found. Stop.
2 0
# empty makefile
make: *** No targets. Stop.
2 0
# dummy makefile entry
inside makefile
0 0
ok
# program with error
gcc target.cc
target.cc: In function ‘int main()’:
target.cc:1:12: error: ‘error’ was not declared in this scope
int main(){error; return 0;}
^
makefile:2: recipe for target 'a' failed
make: *** [a] Error 1
target.cc:1:12
2 0