Shell初体验(二) —— Shell语法之变量、注释和字符串(一)

版本记录

版本号 时间
V1.0 2023.07.17 星期一

前言

Shell脚本相信大家都用过,Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。Shell 脚本(shell script),是一种为 shell 编写的脚本程序。大家平时说的和用到的都是指的是shell脚本编程,不是指开发shell自身。这个模块我们就一起来看下shell脚本编程。感兴趣的可以看下面几篇文章。
Shell初体验(一) —— Shell入门(一)

变量

1. 变量的命名

一个命名的简单示例

name="dodo"

变量的命名要遵循下面规则

  • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头
  • 中间不能有空格,可以使用下划线 _
  • 不能使用标点符号
  • 不能使用bash里的关键字(可用help命令查看保留关键字)

2. 变量类型

运行shell时,会同时存在三种变量:

  • 局部变量:局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
  • 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
  • Shell变量:shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

3. 只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
先看一个简单的示例

#!/bin/bash

host="www.xxx.com"
readonly host
host="www.aaa.com"

下面我们就执行这个脚本,就会发现报错了

./test.sh: line 5: host: readonly variable

报的是第5行错误,提示信息是host是只读变量

4. 删除变量

使用unset命令可以删除变量,语法:

unset variable_name

下面是一个简单示例

#!/bin/bash

host="www.xxx.com"
unset host
echo $host

我们执行这个脚本./test.sh就会发现没有任何输出,因为使用unset删除了变量。

5. 变量的使用

变量的使用需要在变量前加上美元符号$,下面就是一个简单示例:

#!/bin/bash

host="www.xxx.com"
echo ${host}
或
echo $host

执行脚本,都会有下面输出:

www.xxx.com

需要说明的是:{}这个大括号是非必须的,但是加上是一个好习惯。加花括号是为了帮助解释器识别变量的边界。

可以看下面这个示例

#!/bin/bash

host="www.xxx.com"
echo "This is a $hostname"

这里host变量没有用大括号,解析器就会把hostname当成一个变量,所以就会有下面的输出

This is a 

下面我们加上大括号

#!/bin/bash

host="www.xxx.com"
echo "This is a ${host}name"

接着运行下脚本

This is a www.xxx.comname

可以看见,host被识别为一个已定义变量,可以正常的输出了。

注释

以 # 开头的行就是注释,会被解释器忽略。
Shell脚本的注释可以使用command + /,想去掉注释同理。

字符串

1. 字符串的表示

字符串是shell编程中最常用最有用的数据类型,字符串可以用单引号,也可以用双引号,也可以不用引号。
单引号

string='abcdefg'

单引号字符串的限制:

  • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
  • 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。

双引号

#!/bin/bash

string="abcdefg"
str="\"$string\"是前7个字母"
echo $str
//输出
"abcdefg"是前7个字母

双引号的优点:

  • 双引号里可以有变量
  • 双引号里可以出现转义字符

2. 字符串的长度

语法:字符串的长度使用${#string},string是字符串变量名。

看下面一个示例

#!/bin/bash

string="abcdefg"
echo ${#string}
//输出
7

变量为字符串时,${#string} 等价于 ${#string[0]}

#!/bin/bash

string="abcdefg"
echo ${#string[0]}
//输出
7

3. 子字符串

可以通过下面语法获取字符串中的子字符串

语法:${string:index:length},这里string是字符串变量,index是下角标,length是要截取的字符串长度。

可以通过下面示例获取子字符串

#!/bin/bash

string="abcdefg"
echo ${string:0:3}
//输出
abc

可以看见,输出从索引0开始的长度为3的子字符串

4. 字符串的拼接

字符串的拼接,可以使用单引号,也可以使用双引号。
双引号拼接

#!/bin/bash

name="liLei"
greeting="hello, nice to meet you, ${name}!"
echo $greeting
#!/bin/bash

name="liLei"
greeting="hello, nice to meet you, "$name"!"
echo $greeting

上面俩种拼接方式的输出都是一样的

hello, nice to meet you, liLei!

单引号拼接

#!/bin/bash

name="liLei"
greeting='hello, nice to meet you, '$name'!'
echo $greeting
hello, nice to meet you, liLei!

再看下面这种形式

#!/bin/bash

name="liLei"
greeting='hello, nice to meet you, ${name}!'
echo $greeting
hello, nice to meet you, ${name}!

后面这种样式,可以说明单引号里这么引用变量是无效的,会被当成字符串,原样输出。

5. 查找字符中字符的位置

expr index方法

语法:expr index string1 string2,在string1中找到string2的位置。

我们看下下面简单示例:

#!/bin/bash

string="hello world"
result=`expr index "$string" ll`
echo $result

我们运行脚本会发现报错了

expr: syntax error

这个提示很好理解,提示意思就是expr有语法错误,但是仔细检查了好几遍并没发现有什么错误。接着我们在终端运行下面命令。

man expr

可以看见一个命令的使用说明,往下拉可以看见下面提示:

STANDARDS
     The expr utility conforms to IEEE Std 1003.1-2008 (“POSIX.1”).

     The extended arithmetic range and overflow checks do not conflict with POSIX's requirement that arithmetic be done using signed longs, since they
     only make a difference to the result in cases where using signed longs would give undefined behavior.

     According to the POSIX standard, the use of string arguments length, substr, index, or match produces undefined results.  In this version of expr,
     these arguments are treated just as their respective string values.

HISTORY
     An expr utility first appeared in the Programmer's Workbench (PWB/UNIX).  A public domain version of expr written by Pace Willisson <pace@blitz.com>
     appeared in 386BSD-0.1.

意思就是

根据POSIX标准,使用字符串参数length,substr,index或match会产生不确定的结果。
在此版本的expr中,这些参数被视为它们各自的字符串值。也就是没有这些方法。

继续查了下资料

bash: "expr index string1 string2" gives "syntax error"
In a bash script, I was trying to use the command
 
expr index string1 string2

to find the position of string2 in string1, but this does not work on OS X while it works ok on several Linux machines. Reading the man page, I realized expr does something quite different on OS X than on Linux. 

https://discussions.apple.com/thread/923299
The expr in Linux is generally GNU expr. Mac OS X uses BSD expr which does not have the index command.

那说明这个index方法在Mac OS上已经不能用了。大家有别的系统的可以在自己机器上尝试下,我就不给大家试了。

awk

我们可以使用awk去匹配,看下面这个示例

#!/bin/bash

echo "This is a test" | awk '{printf("%d\n", match($0, "is"))}'

这个示例很清晰,就是找字符串"This is a test""is"的索引,这里可以看见"is"出现了2次,我们运行下,如下输出:

3

可以看见是找到了,并且索引为3,也就是找到的是"This"中的"is",是符合预期的,且索引是从1开始的。所以:

  • 这里是求子字符串所在的第一个符合条件的索引
  • 找到则返回指定的正值,找不到符合的则返回0
  • 如果可以找到,那索引是从1开始的

后记

本文讲述了Shell中的变量和字符串,感兴趣的给个赞或者关注,有问题的话,欢迎批评留言指正。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345