shell编程中星号(asterisk “*”)的坑

今天分享一个有关shell编程中由通配符引起的问题。

1. 问题代码

cat test.logs

4567890 *
##*************************************##
rtyuio**tyuio432
##*************************************##
*rtyuiop*2* yuiop
##*************************************##
rtyuiop(3 * 4)iuytr
##*************************************##
8765432

cat script.sh

#!/usr/bin/env bash

# 主要功能是将 非##开头 的每行纪录写入到文件中,每个文件保留一行纪录
logsname=test.logs
i=100
while read line
do
    if [[ $line =~ '##' ]];then
        ((i++))
    else
        echo $line >> $i.txt
    fi
done < "${logsname}"

运行script.sh剧本的效果:
shell编程中星号(asterisk "*")的坑

从图片上红框部门可以看到:

4567890 * 被替换为 4567890 script.sh test.logs
rtyuiop(3 * 4)iuytr 被替换为 rtyuiop(3 100.txt 101.txt 102.txt script.sh test.logs 4)iuytr

快速上手 Python 命令行模块 Click

其他行都正常打印效果,为什么这两行会有问题呢?其他行也有星号,为什么没有被替换呢?

2. 缘故原由剖析

凭据输出效果可以判断出问题的代码:echo $line >> $i.txt

首先,先容一下shell执行剧本的原理:

  1. shell读取整个剧本文件,然后从上到下依次执行每一行
  2. 假设当前line=4567890 *,当shell执行echo $line >> $i.txt
    1. 首先,shell卖力替换$line的值为:4567890 *,此时代码是:echo 4567890 * >> $i.txt
    2. 然后,shell在执行echo下令之前,检查下令的参数中是否有通配符(PS:此时echo的参数:4567890 *)
    3. 很明显,*是通配符,shell卖力剖析通配符,shell会将通配符看成路径或文件名在磁盘上征采可能的匹配:若符合要求的匹配存在,则举行替换(路径扩展);否则就将该通配符作为一个通俗字符参数传递给echo,然后再由echo举行处置。
    4. 剖析完通配符后,*被替换为script.sh test.logs,此时echo下令的参数是:4567890 script.sh test.logs
    5. 最后,shell执行echo 4567890 script.sh test.logs,然后将echo下令执行的效果重定向到文件中。

Tips:

通配符看起来有点像正则表达式,然则它与正则表达式差别的,不能相互混淆。可以把通配符理解为shell能够处置的特殊字符。而且shell的通配符涉及的只有 “*, ?, [], {}” 这几种。

通配符是shell自身支持的,而正则表达式需要相关工具的支持:grep,awk,vi,perl。在文本过滤工具里,都是用正则表达式,好比像awk,sed等,正则表达式是针对文件的内容通配符多用于文件名或者路径上,好比查找find,ls,cp等。

3. 解决方案

凭据上面的剖析可以知道,$line被替换后,通配符*再次被shell剖析。哪有什么设施可以防止shell剖析通配符呢?

  1. 使用引用变量:"$line"在两头加上引号,这样"$line"就变成了一个字符串”4567890 *”,而不是两个单独的字符串。
  2. 引用变量可防止分词和通配符扩展(也就是shell剖析通配符),而且可以防止在变量中包罗空格、换行符、通配符等时造成剧本中止。
  3. 在shell编程中总是使用引用变量的方式,这是一个优越又平安的编码习惯。

4. 参考资料

  1. Reading asterisk character (*) from a file in bash
  2. When to wrap quotes around a shell variable?
  3. Security implications of forgetting to quote a variable in bash/POSIX shells
  4. shellcheck.net-finds bugs in your shell scripts.
  5. Linux Shell 通配符、元字符、转义符使用实例先容

原创文章,作者:28x0新闻网,如若转载,请注明出处:https://www.28x0.com/archives/475.html