bash中这个奇怪的符号“:>”是什么意思

die*_*403 48 bash

我在脚本中找到了一些东西,但不属于主脚本。有:>一条线。

你能给我解释一下这是什么意思吗?

:> file
while read A B C D E; do echo "$A;$B;$D;$E;$C" >> file; done < otherfile
Run Code Online (Sandbox Code Playgroud)

Dav*_*ill 46

在 bash 脚本的一行中有 :> 。这是什么意思?

:> file
Run Code Online (Sandbox Code Playgroud)

这是一个简短的说法:

  • 如果file不存在,则创建它,否则将其截断为0字节。

这意味着您可以确定它file存在并且它是空的。

您也可以使用> file:> file更便携。

请参阅堆栈溢出问题“:”(冒号)GNU Bash 内置函数的目的是什么?想要查询更多的信息。

  • @diego9403:`read` 从标准输入获取输入。就其本身而言,它会读取您键入的内容。由于 stdin 已被重定向到 `&lt;otherfile`,所以 `otherfile` 的内容被“输入”到 stdin 中。因此,`read` 将值逐行放入变量 $A、$B、$C、$D 和 $E 中。 (2认同)

Ark*_*zyk 29

它看起来像是一种创建新文件的奇特方式。Inbash :是一个空命令:

$ type : 
: is a shell builtin 
$ help : 
:: :
    Null command.

    No effect; the command does nothing.

    Exit Status:
    Always succeeds.
Run Code Online (Sandbox Code Playgroud)

>将输出重定向:到一个文件。

  • 如果文件已经存在,它也会截断文件...... (2认同)
  • 是的,这就是 `&gt;` 的作用 (2认同)
  • `:` 是 `true` 的简写。可能在某些 shell 中,`true` 不是内置函数吗?两者都是 bash 的内置函数。 (2认同)

Pet*_*des 12

:是 的另一个名称true。两者都是在bash shell内建命令,但没有/bin/:,只有一个/bin/true。输出重定向使 shell 指向open(2)带有O_CREAT|O_TRUNC. 如果没有写入任何内容,则它保持零长度。

将这两部分放在一起,:> file是截断文件的一个相当常见的习惯用法。不过,大多数人会尝试通过编写 使其看起来不那么奇怪: >file


由于您在有关第 2 行的评论中提出了疑问,因此我会将我的评论转化为答案。(即使你没有在你的问题中问这个。)

第二行是一个循环,它从otherfile一些命名变量中读取行。循环体使用分隔符echo打印它们,;而不是它们之前的任何空白。 file每次迭代都会关闭并重新打开(用于追加),因为重定向在循环内。使用while ...;do read -r ...;done <otherfile >file会少一些,并且避免首先截断文件的需要。read -r不吃\作为逃避字符。

bash 中的文本处理非常慢。其中一部分是不可避免的:read必须一次一个字节(read(2)每个字节一个系统调用)以避免超出行尾。最好使用正确的工具来完成这项工作:

awk -vOFS=';' '{ print $1, $2, $4, $5, $3 }' -- otherfile  >file
Run Code Online (Sandbox Code Playgroud)

--意味着如果您的脚本otherfile被命名为类似--version.

将输出字段分隔符设置为;意味着您可以将多个字段作为参数传递以进行打印。Shellread将带有空格的整个行的其余部分分配给最后一个变量,但没有办法告诉 awk 只拆分为 5 个。如果这很重要,也许继续使用 bash 循环,因为它在 awk 中不方便。Perl 使这变得容易,因为它split可以采用 max-fields 参数,但它的启动速度比 awk 慢得多。

实际上,结果并没有那么难,只是一个难看的正则表达式。为了获得剩余的行而不是$5在 awk 中,循环字段仍然会丢失其原始空白。我的第一个可行的想法是使用gensubon $0(整行)删除前 4 个字段(即非空格后跟空格),留下所有其他内容:

awk -vOFS=';' '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1); print $1, $2, $4, tail, $3 }' -- otherfile >file
Run Code Online (Sandbox Code Playgroud)

我在第一次尝试时就做对了,但我对自己印象深刻的事实说明了 awk 代码的可读性。>.<

请注意它如何与print以前相同,但用tail代替$5

echo 'A  B c DD    e      f g    f' | 
  awk -vOFS=\; '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1);
   print $1, $2, $4, tail, $3 }'

A;B;DD;e       f g    f;c
Run Code Online (Sandbox Code Playgroud)

如果我可以复制/粘贴文字并在输出中显示它通过,这将更令人印象深刻。用 ^Q 在 bash 中输入一个。ctrl-Q 表示将下一个按键引用为文字字符,因为 bash 的 emacs 样式的行编辑与实际的 emacs 相同。

http://mywiki.wooledge.org/BashFAQ有一些关于脚本编写的有用内容,无论您向脚本抛出什么数据或文件名都不会中断。