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脚本的结果:
从图片上红框部分可以看到:
4567890 *
被替换为4567890 script.sh test.logs
rtyuiop(3 * 4)iuytr
被替换为rtyuiop(3 100.txt 101.txt 102.txt script.sh test.logs 4)iuytr
其他行都正常打印结果,为什么这两行会有问题呢?其他行也有星号,为什么没有被替换呢?
2. 原因分析
根据输出结果可以判断出问题的代码:echo $line >> $i.txt
首先,介绍一下shell执行脚本的原理:
- shell读取整个脚本文件,然后从上到下依次执行每一行
- 假设当前line=4567890 *,当shell执行
echo $line >> $i.txt
时- 首先,shell负责替换
$line
的值为:4567890 *,此时代码是:echo 4567890 * >> $i.txt
- 然后,shell在执行echo命令之前,检查命令的参数中是否有通配符(PS:此时echo的参数:4567890 *)
- 很明显,
*
是通配符,shell负责解析通配符,shell会将通配符当作路径或文件名在磁盘上搜寻可能的匹配:若符合要求的匹配存在,则进行替换(路径扩展);否则就将该通配符作为一个普通字符参数传递给echo,然后再由echo进行处理。 - 解析完通配符后,
*
被替换为script.sh test.logs
,此时echo命令的参数是:4567890 script.sh test.logs
- 最后,shell执行
echo 4567890 script.sh test.logs
,然后将echo命令执行的结果重定向到文件中。
- 首先,shell负责替换
Tips:
通配符看起来有点像正则表达式,但是它与正则表达式不同的,不能相互混淆。可以把通配符理解为shell能够处理的特殊字符。而且shell的通配符涉及的只有 "*, ?, [], {}" 这几种。
通配符是shell自身支持的,而正则表达式需要相关工具的支持:grep,awk,vi,perl。在文本过滤工具里,都是用正则表达式,比如像awk,sed等,正则表达式是针对文件的内容。 通配符多用于文件名或者路径上,比如查找find,ls,cp等。
3. 解决方案
根据上面的分析可以知道,$line
被替换后,通配符*
再次被shell解析。那有什么办法可以防止shell解析通配符呢?
- 使用引用变量:
"$line"
,在两端加上引号,这样"$line"
就变成了一个字符串"4567890 *",而不是两个单独的字符串。 - 引用变量可防止分词和通配符扩展(也就是shell解析通配符),并且可以防止在变量中包含空格、换行符、通配符等时造成脚本中断。
- 在shell编程中总是使用引用变量的方式,这是一个良好又安全的编码习惯。
4. 参考资料
- Reading asterisk character (*) from a file in bash
- When to wrap quotes around a shell variable?
- Security implications of forgetting to quote a variable in bash/POSIX shells
- shellcheck.net-finds bugs in your shell scripts.
- Linux Shell 通配符、元字符、转义符使用实例介绍
shell编程中星号(asterisk "*")的坑的更多相关文章
- shell编程中的单/双 小括号, 中括号, 大括号
linux shell中的变量类型?分字符串或者数字或者bool类型吗? 参考: http://www.cnblogs.com/nufangrensheng/p/3477281.html 不分! sh ...
- Shell编程中Shift的用法
Shell编程中Shift的用法 位置参数可以用shift命令左移.比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1.$2.$3丢弃,$0不移动.不带参数的shif ...
- Shell编程中while与for的区别及用法详解【转】
在shell编程中经常用到循环,常用的循环有for和while循环两种.while循环默认以行读取文件,而for循环以空格读取文件切分文件,本篇就结合现网的一些使用示例说说二者的用法和区别. 一.常用 ...
- Linux Shell编程中的几个特殊符号命令 & 、&& 、 ||
https://blog.csdn.net/hack8/article/details/39672145 Linux Shell编程中的几个特殊符号命令 & .&& . || ...
- shell编程中的if语句
if语句在任何编程中都是必不可少.至关重要的分支语句,shell也是如此,只不过各种编程中的方式和格式有点不太一样 shell编程中的if语句基本格式如下: if [ X$1 = XA ];then ...
- shell编程中如何执行oracle语句
shell编程中如果向oracle中插入数据之类的,需要先把执行语句放到文件中,然后再@这个文件执行 有如下俩种方式供参考: SQL=`sqlplus user/pwd@orains << ...
- shell编程中的 三种结构: 条件if/选择结构case/循环for/while/until等结构 和 函数的用法
shell 函数的使用 (md中, 列表本身是有格式的, 他要产生缩进, 其次,列表项和列表项之间, 可以留有一个空行, 是合法的, 允许的) shell函数,就是 就相当于一个命令来看待和处理的, ...
- [ SHELL编程 ] shell编程中数值计算方法实例
SHELL编程中经常会涉及到数值计算,有时候对于这些计算命令使用场景容易忘记或者混淆,这里针对常用的命令做个总结.主要包括let.bc.expr.(())等. 1.let 使用格式:let 表达式,表 ...
- shell编程中用户输入处理(shell 04)
shell编程中用户输入处理1.命令行参数2.脚本运行时获取输入 命令行参数 通过空格来进行分割的位置参数 :$+position $0,$1,$2 ....$0 :程序名$1,$2,$3 ... $ ...
随机推荐
- 执行PHP -m报错Xdebug MUST be loaded as a Zend extension
Xdebug扩展安装后执行PHP -m报错: <br /><b>Warning</b>: Xdebug MUST be loaded as a Zend exten ...
- iOS燃烧动画、3D视图框架、天气动画、立体相册、微信朋友圈小视频等源码
iOS精选源码 iOS天气动画,包括太阳,云,雨,雷暴,雪动画. 较为美观的多级展开列表 3D立体相册,可以旋转的立方体 一个仪表盘Demo YGDashboardView 一个基于UIScrollV ...
- 用Excel做数据分析常用函数(数据清理、关联匹配……)
本文总结在使用Excel进行数据分析时,最常用的功能和函数. Excel的功能和函数非常多,用进废退,除了学习基本的函数和功能,最重要的是遇到问题可以快速的搜索并解决. 首先Excel可以处理的数据量 ...
- python Ajax的使用
转自:http://www.cnblogs.com/python-study/p/6060530.html 1.使用Ajax在后台传递参数的示例 要使用Ajax传递参数,需要使用jquery,使用jq ...
- 百度AI技术
利用百度提供接口,实现智能语音 语音合成 -- TTS(text to speech) 注册 在 ai.baidu.com 页面中点击 控制台 ,弹出登陆 / 注册页面 创建应用 登陆成功后,点击左侧 ...
- phpcms数组处理后键值插入(php自带库函数)和自己处理办法比较。
phpcms处理: public function insert($data, $table, $return_insert_id = false, $replace = false) { if(! ...
- [LC] 92. Reverse Linked List II
Reverse a linked list from position m to n. Do it in one-pass. Note: 1 ≤ m ≤ n ≤ length of list. Exa ...
- the extent of|fill in|find itimpossible to|something|the other day|Be man enough to do sth/for sth|cure sb of |draw out| gone over|made for | see someone off,|
area or length; amount 面积,范围:长度:数量 We don't yet know the extent of his injuries (= how bad his injur ...
- Linux 下centos7启动 Tomcat 抛出Can't connect to X11 window server 问题的解决方法
1 问题 今天启动 Tomcat 后,登录页验证码不见了.在 localhost.xxx.log 发现以下错误: org.apache.catalina.core.StandardWrapperVal ...
- 在Docker内安装jenkins运行和基础配置
这里是在linux环境下安装docker之后,在doucer内安装jenkins --------------------docker 安装 jenkins---------------------- ...