如何阻止 sh 解释 '\' 字符?

How do you stop sh from interpretting the '\' character?

`我有一个脚本,我试图从清单文件中读取,将该清单中的 DOS 路径转换为 ​​UNIX 路径,然后对这些文件进行操作。这是我正在尝试调试的代码片段:

while read line
do
    srcdir=$(printf '%s' "$line" | awk -F \ -v OFS=/ '{ gsub(/\r|^[ \t]+|[ \t]+$/, "") } !NF { next } /^\\/ { sub(/^.*\prj\/, "\prj\") } {  =  } 1')
done < manifest.txt

我的输入文件如下所示:

$ cat manifest.txt
\server\mount\directory

当我调试我的 shell 小片段时,我得到以下信息:

+ read line
++ printf %s '\servermountdirectory
'
++ awk -F '\' -v OFS=/ '{ gsub(/\r|^[ \t]+|[ \t]+$/, "") } !NF { next } /^\\/ { sub(/^.*\prj\/, "\prj\") } {  =  } 1'
+ srcdir=\servermountdirectory

所以...无论是在读取还是在 printf 中,\ 字符都被解释为转义字符——我该如何解决这个问题?

注意...我知道我可以在 awk 中 运行 while 循环...问题是在我的真实程序中,我在 while 循环中还有其他需要用 "$srcdir" 完成的事情——为此,sh 是正确的工具……所以我真的需要 sh.

中的解决方案

来自posix read

By default, unless the -r option is specified, < backslash> shall act as an escape character. An unescaped < backslash> shall preserve the literal value of the following character, with the exception of a < newline>. If a < newline> follows the < backslash>, the read utility shall interpret this as line continuation. The < backslash> and < newline> shall be removed before splitting the input into fields. All other unescaped < backslash> characters shall be removed after splitting the input into fields.

和:

-r
Do not treat a character in any special way. Consider each to be part of the input line.

刚刚:

while read -r line; do

还要记住,如果没有 IFS=,这将不会保留尾随和前导空格。

记得永远做 read -r。这是一个很好的阅读:bashfaq How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?.

还要记住,在 bash 中逐行读取文件效率非常低。使用命令、工具、流和管道来处理整个文件会更好。如果必须逐行读取文件,让"preprocessing"阶段解析整个文件,然后逐行读取:

 awk .... manifest.txt |
 while read -r srcdir; do
    echo "$srcdir"
 done

或者使用命令重定向,如果你需要在同一个 shell:

中循环到 运行
 while read -r srcdir; do
    echo "$srcdir"
 done  < <(awk ... manifest.txt)