我正在将修改后的命令的脚本(命令?)添加head
到我的 ~/.bashrc 中。它按预期处理输入,无论是手动输入、从通配符派生还是由 stdin 提供。但是,如果我忘记向 提供参数headj
,我的终端就会挂起并且无法使用 Ctrl-C 恢复。
echo
这是我的代码(出于调试目的进行了一些调用:
headj(){
echo "script makes it this far without arguments"
IFS=" " read -r -a input <<< "${@:-$(</dev/stdin)}"
echo "but but crashes before getting here"
#
for i in ${input[@]}; do
echo -e "███████████████████████████████████████████████████████████████████████████████"
echo -e "headj $i start"
head -50 "$i"
done
}
它的行为如下:
$ headj list1
script makes it this far without arguments
but not this far
███████████████████████████████████████████████████████████████████████████████
headj list1 start
a
b
$ headj list*
script makes it this far without arguments
but not this far
███████████████████████████████████████████████████████████████████████████████
headj list1 start
a
b
███████████████████████████████████████████████████████████████████████████████
headj list2 start
c
d
$ ls -1 li* | headj
script makes it this far without arguments
but not this far
███████████████████████████████████████████████████████████████████████████████
headj list1 start
a
b
███████████████████████████████████████████████████████████████████████████████
headj list2 start
c
d
$ headj
script makes it this far without arguments
这就是它挂在那里的地方。
我尝试使用读取输入input=( ${@:-$(</dev/stdin)} )
但得到相同的错误。在脚本开头添加此代码可以处理错误。
if [ -z ${*:+x} ]; then
echo "headj requires at least one argument"
return
fi
有一个更好的方法吗?另外,是否有一个关键字我应该搜索此类问题?
答案1
假设您只在没有参数或错误的管道的情况下运行它,并且不想将文件名写入函数的标准输入(为什么要这样做),我会添加一个检查以查看标准输入是否是 tty:
headj() {
local files=()
if [ "$#" -gt 0 ]; then
files=("$@")
elif ! tty >/dev/null; then
readarray -t files
else
echo "Will not read filenames from a tty!" >&2
fi
for file in "${files[@]}"; do
echo "do something with $file..."
done
}
所以,这有效:
$ ls *.txt |headj
do something with test.txt...
但这抱怨:
$ headj
Will not read filenames from a tty!
请注意,read
您使用的命令会用空格分割文件名,所以我会避免这样做,因此上面的参数数量和数组的条件。readarray
应该读取换行符分隔的项目列表,这就是ls
andfind
产生的内容(通过管道传输时),但这当然意味着嵌入换行符的文件名不起作用。
(也许有点吹毛求疵,但我也不会"$@"
在参数<<<
或作业中使用,因为它应该产生多个单词,但在这些情况下它无法做到这一点。使用<<< "$*"
会更清楚地表明其意图是将单个字符串的参数。)
至于为什么 ^C 不起作用,我不能重复,它看起来不像该函数应该这样做。
答案2
我刚刚学会了如何将函数添加到 bashrc 中。感谢那。尝试这个来解决你的问题。
headj(){
ARG=${1? Error. Please, provide the input file. Example: headj filename}
#echo "script makes it this far without arguments"
IFS=" " read -r -a input <<< "${@:-$(</dev/stdin)}"
#echo "but but crashes before getting here"
#
for i in ${input[@]}; do
echo -e ""`enter code here`
echo -e "headj $i start"
head -50 "$i"
done}
$headj
bash: 1: 错误。请提供输入文件。示例:headj 文件名
带管道的示例
$echo "It works for me." > answer.txt
$ cat answer.txt
这个对我有用。
$headj answer.txt | awk '{print $_}'
headj 答案.txt 开始
这个对我有用。
headj answer.txt | awk '{print $_}' | sed 's/me./me. It should work for you too./g'
headj 答案.txt 开始
这个对我有用。它应该也适合你。