shell 多个引号冲突_Shell 引号嵌套

本文详细探讨了Shell脚本中引号的使用,尤其是多重引号和嵌套的情况。解释了系统从前往后匹配引号的规则,以及如何通过转义字符正确处理引号以确保命令功能的正确性。文中通过实例分析了单引号、双引号和倒引号的使用场景,以及在命令替换和变量赋值中如何避免引号冲突。
摘要由CSDN通过智能技术生成

在写shlle脚本或者自定义alias时有一个坑总是无法避开,那就是引号,不管如何尝试系统总是无情的提示“ unmatched ' ”,多方寻找终得正解,遂做此记录。

先抛结论:

1、在使用多重引号时系统是从前往后看的,能匹配就算一对,所以这样一对一对的断句将整个命令串分为若干部分;

2、为了使系统识别后(被识别的引号会消失)的命令串功能正确,需要使用转义字符手动的在合适的地方加入合适的引号;

下面举例来谈。首先明了为何要用引号,不外乎如下几种:

将不连续的一串(比如包含空格)作为一个整体,需用单引号或双引号括起来,区别在于双引号仍能解析其中的变量等;

倒引号用于命令替换,不过倒引号一般不嵌套,在此主要讨论单双引号的嵌套。

比如下面这个命令:

gnome-terminal --tab -t "$start-$end"

-e 'bash -c 'sleep 1m;echo "$start $end" ' '

第一行"$start-$end"是因为其中有变量一般需要用双引号保护一下,但其实这里不加也可以的,第二行“$start $end”也是,而且这里还有一个空格,想要表示他们作为一个整体输出就用了双引号括起来,但其实好像不用echo也能识别的;

第二行-e后面有一对''将一串复杂的命令括了起来同样也是表示他们作为一个整体作为-e的参数,这里把''换成""问题也不大,只不过大家习惯用单引号来括起复杂的命令;

第二行-c后面同样用了一对''原理同上,表示那两条命整体作为-c的参数。

但其实这样的写法系统是不认的,它是这样断句的(第行没问题,接下来我们只关心-e后面的写法):

即开头提到的从前往后数,能凑一对就先凑一对,这样以看到中间sleep 1m;echo是不连续的(sleep后面有格)。正确的写法有下面四种:

头大不 : )

前2条还是那个思路,从前往后挨个配对,断句都用下线表示了,其中穿插的 \" 和 \'是出于功能的考虑,即我想在那个地方人为的加引号,具体看下面编译之后的就明白了;

3和4两条就是简单的单双引号嵌套,并且是单双交替的,这样就比较简单,可以由内而外的看,如3,第一是'$start $end',第二层是"sleep 1m;echo'$start $end' ",第三层是'bash -c "sleep 1mecho '$start $end' " '。注意,这样来看与上述从往后挨个匹配并不冲突,只是这样更清楚。

第五条是不用单引号,只用转义符使大家连成一个整体这样写语法上是没问题的,但是功能是不对的,因sleep\ 1m由于转义符导致1m不能与sleep连成一个小体,及1m不能被sleep识别,而是被算作一个与sleep等级的了。可见只用转义符这种方法只适用于单层命(见下面参考链接1),不太适用于嵌套的,嵌套还是用引号。

再来看这些命令经过系统识别以后长啥样,注意,被识为配对的引号都会消失,但一次识别只会消失最外面层:

可见只消掉最外面一层的话12和34的方式看起来是不一的,以为12是用相同的引号做的嵌套,而34是拿不同的号做的嵌套,所以看起来更直观。

再做一层解析如下,注意这层解析只是我认为的把它还成我们正常写命令的样子,上面经过一层解析之后的命串系统已经可以执行起来了。下面这些只是他们看起来直观的样子,也是我们最初想写的命令:

可以看出2和3.1等价,而3.2由于bash -c内部这层使的是相同的引号做的嵌套(由外而内3,2,1三层,它第层和第2层用的不同引号,第2层和第1层用的相同引号,所以与他们略有不同。

本来1和4.1也应该是等价的,但大家看一下1和2在echo\"$start这里,我都用的\",这里用\"或\'语法上都以,因为系统不会解析转义符,但2的选择是对的,它的是与外面一层不一样的;而1与外面一样,这在功能不对。

这就是开头我们提到的:为了使系统识别后(被识别的引号会消失)的命令串功能正确,需要使用转义字符手动的在合适的地方加入合适的引号。

现在我们将1更正回来,以保证它被解析之后的功能正确性:

好了,看到这里你已经掌握引号嵌套的精髓了,但实际用场景往往都很复杂,比如其实上面这句命令我是想把赋值给一个变量的,众所周知赋给变量的必须得是一个体(字符串),So,又要有一层嵌套了 : )

我已经码了一个多小时了(这效率,唉···),所以这只放结果了,聪明的你一定看的懂吧:)(我用的CShell,不同shell赋值略有不同,但本质一的;并且上面34也可以看出用同样的引号做嵌套很麻烦,所这里就没有头铁,而是选择与倒数第二层不同的引号来的)

可以看出,我是无脑按与第三层不同的引号套的第四层但这样34是错的,如上3所示,中间部分不连续,正确法如下:

其实这里 \" 和 \'的选择也是考虑到而功能正确性的,就再赘述了。

最后,最后再送一个alias(同样是csh,别的sh略有别),其实主要是alias和awk都要单引号导致的冲突,握了这套武林绝学,统统都是小意思

:)

万恶的引号。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值