【问题标题】:understanding shell script-- IFS, '' , ##理解 shell 脚本 -- IFS, '' , ##
【发布时间】:2014-08-08 06:19:55
【问题描述】:

我对 shell 脚本非常陌生。 谁能用一种非常简单的语言在下面解释我,或者给我一些链接,在那里我可以找到我正在搜索的确切含义,如下面的代码所示:

文件如何获取值?它是从完成后编写的 grep 命令中获取的吗?

dir=$1 str=$2
while IFS= read -rd '' file;   #What '' is doing?
do
    base=${file##*/}  #Please explain
dir=${file%/*}    #Please explain
done < <(exec grep -ZFlR "$str" "$dir")

提前致谢 :)

【问题讨论】:

标签: linux shell


【解决方案1】:

第一行用于读取grep -ZFlR "$str" "$dir"传递的原始输入。

while IFS= read -rd '' file;

正如您在grep 中指定的-Z 一样,它将输出一个零字节,而不是grep 通常使用的换行符分隔文件名。因此,在读取命令中还指定了 -d 选项,该选项引用了分隔符。 至于IFS=,这样做是为了清空 IFS(内部字段分隔符)以保留前导和尾随空格。更多阅读here

下一行:

base=${file##*/}

$file前面删除以斜线结尾的任何字符中最长的匹配项。所以类似于:

/abc/def/jhg

-------->

strips off /abc/def/

同样是第三行:

dir=${file%/*}

从 $file 的末尾删除最短的匹配项。

/abc/def/jhg

        <----

strips off /jhg. 

更多阅读here

由于您没有询问最后一行,我假设您熟悉它被重定向到 while 循环。

【讨论】:

  • 为什么最后一行使用exec和进程替换? while read ...; do ...; done &lt; &lt;(exec grep ...)grep ... | while read ...; do ...; done 有什么区别?我会假设管道是要走的路。请解释:)
  • 非常感谢。这很有帮助..:)
  • @knittl 我不知道为什么exec 会出现在那里,没有它也可以正常工作,应该只是这样。关于你的第二个问题,我在这里找到了一个很好的解释 => stackoverflow.com/questions/3177507/…。虽然它不适用于这种情况,但一般来说。希望它有所帮助;)。
  • &lt;(exec ...)$(exec ...) 是 konsolebox 的风格 ;)
  • 因为没有exec,shell 默认会召唤另一个分叉并使用那个分叉来执行二进制文件。之后我们不需要做任何事情,所以我们只需要使用 subshel​​l 本身来执行二进制文件。这节省了额外的分叉,还使$! 提供的进程ID 成为exec 调用的实际进程。
【解决方案2】:
while IFS= read -rd '' file;   #What '' is doing?
do

while 循环将读取命令(exec grep -ZFlR "$str" "$dir") 返回的每一行。您会看到它被用来'feed' 数据到最后的循环:done &lt; &lt;(exec grep -ZFlR "$str" "$dir") 从您看到的while 循环开始IFS=。 bash 中的 unsetsInternal Field Separator (IFS) 确定了将给定字符串分隔成单独字段的内容。 (默认的 IFS=$'space tab newline' 你看到写成IFS=$' \t\n')

while 循环以read -rd '' file; 继续,正如所讨论的,输入来自最后的exec grep.. 表达式,read -rd '' file 正在读取该输入直到第一个'' 由@ 指定987654334@ 是与此read 一起使用的分隔符read 然后将匹配的输入存储在变量file 中。 所以'' 只是作为read 的分隔符,由-d 选项指定到read(这解释了为什么IFS未设置 > 一开始,他们想在这种情况下使用特定的'' 分隔符。

    base=${file##*/}  #Please explain

这就是说使用parameter expansion 删除string 中的所有内容,从left 到(并包括)最后一个/ 字符。 (这就是## 的意思)。 它正在从文件名中删除路径信息,只留下base中的文件名

dir=${file%/*}    #Please explain

这是类似的参数扩展,但在这里,我们从%)开始删除所有字符,包括file中的第一个/字符dir 中只留下path 信息。 (有道理)

done < <(exec grep -ZFlR "$str" "$dir")

就像我们上面讨论的那样,只提供循环。

【讨论】:

  • 精彩的解释。谢谢..:)
【解决方案3】:

$file 从read 获取其值,而后者又从输入中读取,该输入在循环结束时被重定向到。 &lt;( ... ) 被称为“进程替换”,它基本上表现为一个文件,其内容是封闭命令的输出。 ##% 是“参数扩展”的实例,它们删除了变量值的一部分。您可以在man bash 中搜索所有术语和结构。

【讨论】:

    猜你喜欢
    • 2014-06-15
    • 2018-12-03
    • 2020-06-17
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多