如何阻止 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)
`我有一个脚本,我试图从清单文件中读取,将该清单中的 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)