Error handling 修改zsh命令以转发错误
我想修改我最近的一个Bash别名以转发错误。以下是别名:Error handling 修改zsh命令以转发错误,error-handling,pipe,zsh,Error Handling,Pipe,Zsh,我想修改我最近的一个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 && xc
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。当错误列表(保存到剪贴板并回显的内容)不为空时,如何向代码添加修改以设置错误标志?您可以通过使用PIPESTATUS
内部变量(该变量在非bash shell中有其他名称)来解决问题。这允许具有管道传递的命令的退出状态的历史记录
您在评论中明确指出,您没有使用
bash
,而是使用zsh
。因此,我的解决方案的一些语法必须更改,因为它们以不同的方式处理PIPESTATUS
变量
在bash中,使用${PIPESTATUS[0]}
,而在zsh中使用${PIPESTATUS[1]}
第一种方法是使用现有别名,如下所示:
makecclip && [ "${pipestatus[1]}" -eq "0" ] && echo "ok"
仅当“${pipestatus[1]}”等于0(生成期间无错误)时,才会运行echo
命令
更方便的解决方案是为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
我试过了,但似乎不起作用。我认为实际上是make改变了pipestatus,但是我也必须重定向错误。它和你的测试一起工作吗?是的,它在我的电脑上工作得很好。我已经编辑了我的问题以添加我使用过的测试。@AdamHunyadi抱歉,我花了一段时间才将我的测试用例形式化为脚本。您可以看到我运行的测试和得到的输出。好的,这就是为什么我指定我的解决方案仅适用于bash
(因为您的问题带有标签)bash
和zsh
具有不同的内部变量。我会根据上下文修改我的答案。当您从控制台调用它时,它是否失败?从带有#的脚本/bin/bash
shebang?从带有#的脚本/bin/zsh
shebang?从这两种情况?