shell脚本如何替换包含换行符的变量
shell script how to substitute variable contains newline
$ ls . > /tmp/tfile.txt
$ flist=`cat /tmp/tfile.txt`
$ echo $flist
a.txt b.txt c.txt
$ echo ${flist#* }
a.txt b.txt c.txt
为什么${flist#* }
不能输出b.txt c.txt
?如何处理变量包含换行符?
${flist#* }
像 $flist
一样展开,但删除了与 *
匹配的最小部分(星号 +space,其中星号匹配零个或多个字符,而 space从开头匹配 space 个字符)。
因此,它从扩展中删除了第一个 space 之前的字符。因此,在您的情况下,它会打印 a.txt
然后看到 space 并退出,因此不会打印 b.txt
和 c.txt
.
如果你输入 echo "${line#*.txt}"
,那么输出将是:
b.txt c.txt
查看此 reference 以了解 bash 中的 #*
。
一般来说,shell 不是处理数据和修改变量的好工具。 (尽管它是与 Unix 一起工作的一个很好的工具,请继续学习和使用它。)一些方言可以在某些方面解决这个问题,但记住复杂的数据处理最好在 shell.
大多数数据处理预计将使用外部工具进行,而不是使用 shell 原语。
这里有几种方法可以修剪您刚刚阅读的文件的第一个条目,最特殊的是:
omit_first_line()
{
tail -n+2 ""
}
flist=$(omit_first_line tfile.txt)
了解如何使用 $(…)
代替反引号,不鼓励使用反引号,因为它们很难配对和引用。
还有许多其他工具可以为您跳过文件中的第一行,例如 sed 或 awk。
如果您正在处理文件,您真的应该考虑使用 find 和 xargs,它们可以很好地协同工作,如
find . -type f -print0 | xargs -0 stat
或
find . -type f -print | { while read filename; do printf 'Filename %s\n' "${filename}"; done }
一般来说,编写过滤器比处理列表更容易。不是将数据存储在列表中,而是使用经典的命令式语言,将数据存储在文件中,每条记录单独一行,并在过滤器之间传输数据。如果您能够直接打印数据,则可能根本不需要将其存储在文件中。
现在,如果您有充分的理由在 shell 中处理您的列表,您可以使用位置参数:
gobble()
(
set -- "$@"
shift
echo "$@"
)
flist='a.txt b.txt c.txt'
flist=$(gobble ${flist})
echo ${flist}
非常感谢您的依赖。最后,我通过 re-assigning flist
和 flist=`echo $flist`;
.
解决了这个问题
$ ls . > /tmp/tfile.txt
$ flist=`cat /tmp/tfile.txt`
$ echo $flist
a.txt b.txt c.txt
$ echo ${flist#* }
a.txt b.txt c.txt
为什么${flist#* }
不能输出b.txt c.txt
?如何处理变量包含换行符?
${flist#* }
像 $flist
一样展开,但删除了与 *
匹配的最小部分(星号 +space,其中星号匹配零个或多个字符,而 space从开头匹配 space 个字符)。
因此,它从扩展中删除了第一个 space 之前的字符。因此,在您的情况下,它会打印 a.txt
然后看到 space 并退出,因此不会打印 b.txt
和 c.txt
.
如果你输入 echo "${line#*.txt}"
,那么输出将是:
b.txt c.txt
查看此 reference 以了解 bash 中的 #*
。
一般来说,shell 不是处理数据和修改变量的好工具。 (尽管它是与 Unix 一起工作的一个很好的工具,请继续学习和使用它。)一些方言可以在某些方面解决这个问题,但记住复杂的数据处理最好在 shell.
大多数数据处理预计将使用外部工具进行,而不是使用 shell 原语。
这里有几种方法可以修剪您刚刚阅读的文件的第一个条目,最特殊的是:
omit_first_line()
{
tail -n+2 ""
}
flist=$(omit_first_line tfile.txt)
了解如何使用 $(…)
代替反引号,不鼓励使用反引号,因为它们很难配对和引用。
还有许多其他工具可以为您跳过文件中的第一行,例如 sed 或 awk。
如果您正在处理文件,您真的应该考虑使用 find 和 xargs,它们可以很好地协同工作,如
find . -type f -print0 | xargs -0 stat
或
find . -type f -print | { while read filename; do printf 'Filename %s\n' "${filename}"; done }
一般来说,编写过滤器比处理列表更容易。不是将数据存储在列表中,而是使用经典的命令式语言,将数据存储在文件中,每条记录单独一行,并在过滤器之间传输数据。如果您能够直接打印数据,则可能根本不需要将其存储在文件中。
现在,如果您有充分的理由在 shell 中处理您的列表,您可以使用位置参数:
gobble()
(
set -- "$@"
shift
echo "$@"
)
flist='a.txt b.txt c.txt'
flist=$(gobble ${flist})
echo ${flist}
非常感谢您的依赖。最后,我通过 re-assigning flist
和 flist=`echo $flist`;
.