直到现在才意识到你可以这样做:
: >> file
Run Code Online (Sandbox Code Playgroud)
它似乎在功能上类似于:
touch file
Run Code Online (Sandbox Code Playgroud)
大多数资源似乎更喜欢 touch 这个内置的 shell 有什么原因吗?
POSIX 将文本文件定义为:
包含组织成零个或多个行的字符的文件。这些行不包含 NUL 字符,并且长度不能超过 {LINE_MAX} 个字节,包括 <newline> 字符。尽管 POSIX.1-2017 不区分文本文件和二进制文件(参见 ISO C 标准),但许多实用程序仅在对文本文件进行操作时产生可预测或有意义的输出。具有此类限制的标准实用程序总是在其 STDIN 或 INPUT FILES 部分中指定“文本文件”。
来源:http : //pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_403
但是,有几件事我觉得不清楚:
文本文件必须是普通文件吗?在上面的摘录中没有明确说明文件必须是常规文件
如果文件只包含一个字符和一个字符(即不以换行符结尾的单个字符),是否可以将文件视为文本文件?我知道这个问题可能听起来很挑剔,但他们使用“字符”一词而不是“一个或多个字符”。其他人可能不同意,但如果他们的意思是“一个或多个字符”,我认为他们应该明确地说出来
在上面的摘录中,它提到了“线条”。我发现了四个名称中带有 line 的定义:“Empty Line”、“Display Line”、“Incomplete Line”和“Line”。我是否应该推断它们的意思是“线”,因为它们省略了“空”、“显示”和“不完整”——或者所有这四个定义都被认为是上面摘录中的一条线?
此文本块之后出现的所有问题都取决于推断“字符”表示“一个或多个字符”:
此文本块之后的所有问题都取决于推断,在上面的摘录中,一行被定义为“行”,并且应排除名称中包含“行”的其他三个定义:
“零行或多行”中的“零”是否意味着如果文件包含一个或多个未以换行符终止的字符,则仍可将其视为文本文件?
“零行或多行”是否意味着一旦单个“行”(0 个或多个字符加上终止换行符)开始发挥作用,最后一行成为“不完整行”(一个或多个非文件末尾的换行符)?
“无 [无行] 的长度可以超过 {LINE_MAX} 个字节,包括换行符”是否意味着文本文件中任何给定“行”中允许的字符数有限制(顺便说一句, Ubuntu 18.04 和 FreeBSD 11.1 上的 LINE_MAX 是“2048”)?
从POSIX 规范的Shell 命令语言页面:
如果 shell 命令文件的第一行以字符“#!”开头,则结果未指定。
为什么#!
POSIX 未指定的行为?我觉得令人困惑的是,如此便携和广泛使用的东西会有未指明的行为。
在 ash、dash 和 bash 上,当我跑步时
$ echo ab$
Run Code Online (Sandbox Code Playgroud)
它返回
ab$
Run Code Online (Sandbox Code Playgroud)
这种行为是由 POSIX 指定的还是只是符合 POSIX 的 shell 中的常见约定?我在 POSIX Shell 命令语言页面上找不到任何提到此行为的内容。
file.txt 的内容(不奇怪,POSIX 定义的文本文件)
iguana
gecko
anole
Run Code Online (Sandbox Code Playgroud)
示例脚本:
#!/bin/sh
string="$(cat file.txt)"
printf '%s' "$string"
Run Code Online (Sandbox Code Playgroud)
示例输出:
[coolguy@somemachine ~]$ ./script.sh
iguana
gecko
anole[coolguy@somemachine ~]$
Run Code Online (Sandbox Code Playgroud)
最后一个换行符发生了什么?为什么除了最后一个都保留了换行符?如果已经有一个换行符,我们似乎不必使用 echo 添加一个换行符。
我想澄清一下,我不是在谈论如何在解释的 shell 级别上转义字符。
据我所知,只需要转义两个字符:%
和\
要打印文字%
,您必须使用前面的 将其转义%
:
printf '%%'
Run Code Online (Sandbox Code Playgroud)
要打印文字,\
您必须使用前面的 将其转义\
:
printf '\\'
Run Code Online (Sandbox Code Playgroud)
是否有任何其他情况我需要转义字符才能按字面意思解释?
当我在 Xubuntu 16.04 上运行这四个命令时,无论是在本地还是通过 ssh,它们似乎都在做完全相同的事情:
export DISPLAY=:0.0 #not necessary unless you have logged in over ssh instead of starting a terminal locally
Run Code Online (Sandbox Code Playgroud)
gedit &
Run Code Online (Sandbox Code Playgroud)gedit & disown
Run Code Online (Sandbox Code Playgroud)nohup gedit
Run Code Online (Sandbox Code Playgroud)nohup gedit & disown
Run Code Online (Sandbox Code Playgroud)我不明白两者之间的区别gedit &
,gedit & disown
因为如果我杀死父终端或退出 ssh 会话,在任何一种情况下,gedit 似乎都被“否认”。
至于二和三,我看到的唯一区别是命令输出被记录到一个单独的文件中,并且即使产生 bg 进程的原始 shell 会话被终止,也会继续记录到该单独的日志中。
至于三和四,我一直在读到有技术差异,但完全不明白为什么你更喜欢一个而不是另一个。
我应该使用哪一种?我已经看到教程和问答中使用的所有四个命令,尽管有一些非常好的答案描述了 nohup 和 disown 之间的技术差异,但我似乎无法得到明确的建议(除了出于日志记录目的或 shell 兼容性)哪个我应该用。
我想将两个数字与bc
. 根据StackOverflow 上这个高度评价的答案,我可以这样做:
printf '%s\n' '1.2 > 0.4' | bc
Run Code Online (Sandbox Code Playgroud)
bc
发送1
到 STDOUT,表明该语句为真(如果该语句为假,它将返回 0)。
与所有其他运算符不同,关系运算符( '<', '>', "<=", ">=", "==", "!=" )仅作为 if、while、或在 for 语句中。
也许我误解了,但是这种语言似乎不允许使用上面示例中使用的语法。
单独使用关系运算符是否bc
违反 POSIX?如果是这样,我应该如何重写我的例子?
这就是我现在用来完成工作的方法:
#!/bin/sh --
string='Aa1!z'
if ! printf '%s\n' "$string" | LC_ALL=C grep -q '[[:upper:]]' || \
! printf '%s\n' "$string" | LC_ALL=C grep -q '[[:lower:]]' || \
! printf '%s\n' "$string" | LC_ALL=C grep -q '[[:digit:]]' || \
! printf '%s\n' "$string" | LC_ALL=C grep -q '[[:punct:]]'; then
printf '%s\n' 'String does not meet your requirements'
else
printf '%s\n' 'String meets your requirements'
fi
Run Code Online (Sandbox Code Playgroud)
这是非常低效和冗长的。有一个更好的方法吗?
#!/bin/sh --
for set_trap_sig in HUP INT QUIT ALRM TERM; do
trap -- '
trap -- - '"${set_trap_sig:?}"' EXIT || exit "$?"
kill -s '"${set_trap_sig:?}"' -- "$$" || exit "$?"' "$set_trap_sig"
done
sleep 15 || exit "$?"
Run Code Online (Sandbox Code Playgroud)
这是我向脚本发送 SIGINT 时发生的情况
user@hostname:/tmp$ ./script.sh
^C./script.sh: 3: ./script.sh: Syntax error: EOF in backquote substitution
Run Code Online (Sandbox Code Playgroud)
这个问题似乎是针对 dash 的。在 ash、bash 和 ksh93 上我没有收到此错误。这特别奇怪,因为我的脚本甚至不包含反引号字符。
如果我删除第 5 行末尾的双引号,$?
错误就会消失。
我是在做一些愚蠢的事情还是dash行为不当?请不要对我的脚本中的错误检查级别发表评论。
我们现在已经确定这是一个非常严重的错误,甚至影响现代版本的 Ubuntu 和 Debian。有谁知道解决方法?
当我跑
user@hostname:~$ su -- root -z
Run Code Online (Sandbox Code Playgroud)
我得到
bash: -z: invalid option
Usage: bash [GNU long option] [option] ...
...
Run Code Online (Sandbox Code Playgroud)
以上是我期望的行为。
当我跑
user@hostname:~$ su -l -- root -z
Run Code Online (Sandbox Code Playgroud)
我得到
-su: -z: invalid option
Usage: -su [GNU long option] [option] ...
...
Run Code Online (Sandbox Code Playgroud)
我使用 invalid 选项-z
只是为了演示哪个命令正在解析该选项。
这种行为让我感到厌烦。su
在我宣布选项结束后继续寻找选项。我错过了什么,这是一个错误还是可怕的设计?