linux shell中几种特殊变量和字符串的截取

哈,Shell字符串截取这事儿吧,确实挺实用的。
我给你捋捋常用的几种情况。

一、截取指定字数
最简单的是直接用${变量:偏移量:长度}这个格式。

比如,你想截取变量mystring="Hello World"的前8 个字符,可以这么做:
bash mystring="Hello World" substring=${mystring:0:8 } echo $substring 输出 Hello Wo
这里0是起始位置,8 是要取的长度。
从0开始,取8 个,所以是Hello Wo。
如果要从第5 个字符开始截取,比如World,那就是:
bash substring=${mystring:4 :5 } echo $substring 输出 World
偏移量是从0开始的,所以第5 个字符就是偏移量4
二、按指定的字符串截取
这个用得也超多,特别是处理路径啊、文件名啊什么的。

主要有这几种:
1 . ${variablestring} 和 ${variablestring}:这是从左到右找。
2 . ${variable%%string} 和 ${variable%string}:这是从右到左找。

和 %% 是强制删除, 和 % 是非强制删除(如果找不到string,变量不变)。
是通配符,匹配任意字符序列。

场景举例:
假设变量path="/home/user/documents/report.doc",你想去掉前面的/home/user/,只留documents/report.doc。

bash 从左向右,截取第一个 /home/user/ 之后的部分 trimmed_path=${path/home/user/} echo $trimmed_path 输出 documents/report.doc
或者也行, 匹配任意字符 trimmed_path=${pathhome/user/} echo $trimmed_path 同样输出 documents/report.doc
再比如,想截取最后一个 / 之后的部分 trimmed_path=${path/} 强制删除最后一个 / echo $trimmed_path 输出 report.doc
或者 trimmed_path=${path%%/} 非强制删除最后一个 / echo $trimmed_path 输出 report.doc
再比如,filename="report_v1 .2 .3 .txt",你想取report.后面的部分:
bash 从左向右,截取第一个 .report 之后的部分 name_part=${filename.report} echo $name_part 输出 v1 .2 .3 .txt
从右向左,截取最后一个 . 后面的部分 ext_part=${filename%.} 截取最后一个 . 后面的 echo $ext_part 输出 report_v1 .2 .3
截取最后一个 . 之前的部分 name_part=${filename%%.} echo $name_part 输出 report_v1 .2 .3
注意看和%的区别:
string / string:从左找string,删掉它和它左边的所有东西。
%string / %%string:从右找string,删掉它和它右边的所有东西。

如果string在中间或者找不到,行为也不同:
bash var="abc1 2 3 xyz" 从左删第一个1 2 3 ${var1 2 3 } 输出 1 2 3 xyz 从左删最后一个1 2 3 ,找不到就原样输出 ${var1 2 3 } 输出 abc
从右删第一个xyz ${var%xyz} 输出 abc1 2 3 从右删最后一个xyz,找不到就原样输出 ${var%%xyz} 输出 abc1 2 3
三、按照指定要求分割
这个不是直接截取,而是用IFS(Internal Field Separator,内部字段分隔符)或者cut命令。

用IFS分割:
可以临时改变IFS的值,然后用read读取。

bash 假设 variable="apple banana cherry" 想按空格分割 IFS=' ' read -r -a fruits <<< "$variable" echo ${fruits[0]} 输出 apple echo ${fruits[1 ]} 输出 banana echo ${fruits[2 ]} 输出 cherry echo ${fruits[@]} 输出 3 (总数) unset IFS 别忘了恢复
read会把分割后的内容存到数组fruits里。
想取后缀名,比如file.tar.gz,想取.gz:
bash filename="file.tar.gz" IFS='.' read -r -a parts <<< "$filename" parts 数组是 ["file", "tar", "gz"] if [ ${parts[@]} -gt 2 ]; then extension="${parts[-1 ]}" 取最后一个元素 echo $extension 输出 gz else echo "没找到后缀名" fi unset IFS
用cut命令:
cut更直接,按字符、字节或字段分割。

bash filename="file.tar.gz" 按 . 分割,取第二个字段 (-f 2 ) extension=$(echo $filename | cut -d '.' -f 2 ) echo $extension 输出 tar
取最后一个字段 (-f -1 ) extension=$(echo $filename | cut -d '.' -f -1 ) echo $extension 输出 gz
取所有字段,用 ; 分隔 echo $filename | cut -d '.' -f - 输出 file;tar;gz
cut -d '分隔符' -f {n}取第n个字段,-f -1 取最后一个字段。

总结一下:
截取指定长度用${变量:偏移量:长度}。
按字符串截取用${变量/string}、${变量string}、${变量%%string}、${变量%string},注意和%以及和%%的区别,还有强制删除和非强制删除。
分割用IFS配合read或者cut。

这些方法组合起来用,处理字符串还是挺方便的。
具体用哪个看情况,有时候cut一行就写完了,有时候IFS read处理数组更顺手。

Linux cut 命令详解

这事儿我太熟了,之前在公司用Linux系统的时候,那可是天天跟cut命令打交道。
记得有一次,我需要从服务器日志里提取出所有的IP地址,那叫一个头疼啊。

当时,日志文件里每一行都有IP地址,但是IP地址之间是乱七八糟的,没有固定的分隔符。
我当时就试了各种方法,最后才想到用cut命令结合正则表达式来搞定。
那是一个星期天的下午,我一个人在办公室,花了大概三个小时才解决。

当时是这样的,我写了个脚本,先用grep提取出包含IP地址的行,然后对每一行用cut命令按照正则表达式分割,最后提取出IP地址。
我那时候用的命令长得像这样:
grep 'IP地址' log.txt | cut -d' ' -E '[0-9 ]{1 ,3 }\.[0-9 ]{1 ,3 }\.[0-9 ]{1 ,3 }\.[0-9 ]{1 ,3 }'
这里的 -d' ' 是指定空格作为分隔符,-E 是告诉cut使用扩展的正则表达式,[0-9 ]{1 ,3 }\.[0-9 ]{1 ,3 }\.[0-9 ]{1 ,3 }\.[0-9 ]{1 ,3 } 这个正则表达式就是用来匹配IP地址的。

这个过程真的很磨人,但是解决了问题之后,我就记住了这个方法。
后来遇到类似的问题,就能迅速解决。
这块儿我敢肯定,你以后肯定也会用到这个方法。
哈哈,讲得有点多,咱们继续聊其他事儿吧。
你最近有什么好玩的事情吗?

linux awk怎么截取字符串

哎哟,这awk的substr用起来是真方便,我以前搞过不少事。
想当年我在上海那会儿,公司日志文件看着就头疼,一溜儿的文本。
我就用这玩意儿,效率高啊。

记得到年底的时候,有个任务,得把所有日志里的时间戳都抠出来。
你想想,日志每行都是这种格式:[2 02 3 -03 -1 5 1 4 :2 3 :01 ] info: something happened. 那时间戳就在中括号里。
我就用了个小技巧:
bash awk '{print substr($0, 2 , 1 0)}' access.log
你看,$0代表整行,从第二个字符开始截取1 0个,刚好就是2 02 3 -03 -1 5 这招真管用,一行命令搞定,比手动复制粘贴强多了。

还有一次,处理一个CSV文件,数据挺多的,第三列有时候字段特别长。
领导说,只要前三字符就行。
我又来这套:
bash awk -F, '{print substr($3 , 1 , 3 )}' data.csv
-F,是告诉awk逗号是分隔符。
第三列$3 截取前三字符,一行搞定。
当时老板还夸我,说比他们以前用的那些脚本都简洁。

不过啊,这东西得小心,起始位置是从1 开始的,不是像Python那样从0开始。
我以前就犯过这种低级错误,想从第一个字符开始截,结果手一抖,写成了substr($0, 0, 5 ),结果啥都没输出,把我好一顿懊恼。
还得注意,起始位置要是超过字符串长度了,就返回空,你得有心理准备。

总的来说,这substr函数在处理文本,尤其是日志啊、数据清洗啊这些场景下,是真香。
你多练练,很快就上手了。

linux 中如何截取2个字符串中间的字符?

用awk处理JSON字段可行。
awk -F '"' '{print $4 }' 从JSON中提取第四个字段。
比如:awk -F '"' '{print $4 }' s 处理变量s里的JSON。
但sed、tr、perl更灵活。
具体看数据格式和需求。
你自己掂量。