处理 bash 脚本/命令中丢失的输入

处理 bash 脚本/命令中丢失的输入

我正在将修改后的命令的脚本(命令?)添加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应该读取换行符分隔的项目列表,这就是lsandfind产生的内容(通过管道传输时),但这当然意味着嵌入换行符的文件名不起作用。

(也许有点吹毛求疵,但我也不会"$@"在参数<<<或作业中使用,因为它应该产生多个单词,但在这些情况下它无法做到这一点。使用<<< "$*"会更清楚地表明其意图是将单个字符串的参数。)

至于为什么 ^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 开始

这个对我有用。它应该也适合你。

相关内容