目前我正在编写一个 Bash 脚本,它具有以下要求:
我知道这getopts将是可移植性方面的首选方式,但 AFAIK 它不支持长选项。
getopt支持长选项,但BashGuide强烈建议反对它:
永远不要使用 getopt(1)。getopt 无法处理空参数字符串或带有嵌入空格的参数。请忘记它曾经存在过。
因此,仍然可以选择手动解析。这很容易出错,会产生相当多的样板代码,而且我需要自己处理错误(我想自己getopt(s)进行错误处理)。
那么,在这种情况下,首选是什么?
目前我正在开发一个更大的 Bash 脚本(它是我的一个开源项目),它开始变得一团糟。我已将逻辑拆分为函数,尽可能使用局部变量,并且只声明了少数全局变量。尽管如此,它变得非常难以维护。
我考虑将脚本分成多个脚本并在我的主脚本中获取它们(类似于其他语言的导入)。
但我想知道这是否是一种可行的方法。首先,采购多个脚本可能会严重减慢脚本的执行时间,其次,它使分发变得更加困难。
那么,这是一个好方法吗,其他(开源)项目是否也这样做?
当我像这样运行 Centos 7 Docker 镜像时
docker run -it centos:7 bash
Run Code Online (Sandbox Code Playgroud)
运行使用Process Substitution 的东西是没问题的(正如预期的那样,Bash 从一开始就支持 Process Substitution - 实际上是 Bash 1.4.x)。
例如:
while IFS= read -r test; do echo $test; done < <(cat anaconda-post.log)
Run Code Online (Sandbox Code Playgroud)
但是当我切换到/bin/sh时,相同的代码不再起作用
/bin/sh
while IFS= read -r test; do echo $test; done < <(cat anaconda-post.log)
sh: syntax error near unexpected token `<'
Run Code Online (Sandbox Code Playgroud)
虽然/bin/sh看起来是Bash
/bin/sh --version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version …Run Code Online (Sandbox Code Playgroud) 我已经使用 tput 定义了红色
red=$(tput setaf 1)
Run Code Online (Sandbox Code Playgroud)
为我的程序中的警告着色。这工作正常:
printf '%sfail\n' "$red"
# prints 'fail' in red
Run Code Online (Sandbox Code Playgroud)
但有一次我想按原样打印出转义序列,例如:
\E[31mfail
我该怎么做?我知道 printf 有一个%q标志,但它逃脱了我不想的其他东西。
我已经写了一个叫bash的功能了,我通过github上分享。现在我正在为安装说明而苦苦挣扎。我知道“安装” bash 函数的两个选项:
.bashrc.bashrc所以,我的想法是建议下载该函数并相应地修改.bashrc文件。
我调查了类似的项目是如何实现这一点的,其中一些甚至.bashrc在安装时操纵文件(即他们将功能放在那里)。这样做似乎很常见,但我觉得.bashrc自动操作是一个坏主意。
那么,什么是首选方式?对此是否有一些共识?
我目前正在开发一个名为 的 shell 脚本,up当使用--help. 输出如下所示:
$ up --help
usage: up [-n levels][--help][--versions][basename]...
Run Code Online (Sandbox Code Playgroud)
这看起来没问题,但我想知道我是否真的需要显示--help和--version选项,因为它们是一个被广泛接受的标准,似乎只会给使用字符串增加噪音。
假设您有以下问题:
根据脚本是否在管道内执行,您希望将-print0参数附加到find.
我可以想到至少两种方法来做到这一点:
[[ -p '/dev/stdin' ]] && local null_terminated='-print0'
find -mindepth 1 -maxdepth 1 ! \( "${args[@]}" \) "$null_terminated"
Run Code Online (Sandbox Code Playgroud)
或者
if [[ -p '/dev/stdin' ]]; then
find -mindepth 1 -maxdepth 1 ! \( "${args[@]}" \) -print0
else
find -mindepth 1 -maxdepth 1 ! \( "${args[@]}" \)
fi
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来做到这一点?问题是针对bash,但sh也欢迎其他 shell 或便携式/标准解决方案的解决方案。
有时在编写脚本时,可能需要将IFS(内部字段分隔符)设置为默认值以外的其他内容,例如更改$*将扩展的方式。
虽然这完全有道理,但我想不出有任何理由IFS在交互式 shell 中设置除默认值之外的任何内容(如果我没记错的话,它是空格、制表符和换行符)。我仍然经常被告知,在交互式 shell 上,我不能期望IFS将其设置为默认值。
这是真的吗?谁能举个实际的例子?