Bash 匹配变量值与读文件操作

Bash 匹配变量值与读文件操作

$(cat file) 与 $(< file) 达成的功能相同,$(< file) 能够更快执行,也就是说你需要用 $(< file) 来代替 $(cat file),以获得更好的性能。下面是一个具体的示例:

	[longyu@debian:22:36:23] ~ $ cat filelist 
	./Screenshot from 2018-10-23 20-03-53.png
	./Screenshot from 2018-10-22 23-06-20.png
	[longyu@debian:22:36:26] ~ $ file=$(cat filelist)
	[longyu@debian:22:36:42] ~ $ echo $file
	./Screenshot from 2018-10-23 20-03-53.png ./Screenshot from 2018-10-22 23-06-20.png
	[longyu@debian:22:36:44] ~ $ time file=$(cat filelist)
	[longyu@debian:22:37:16] ~ $ file=$(< filelist)
	[longyu@debian:22:37:17] ~ $ echo $file
	./Screenshot from 2018-10-23 20-03-53.png ./Screenshot from 2018-10-22 23-06-20.png

如果现在我需要获取变量中的某些内容,并且一般的变量扩展方式无法做到,那么我们通常会这样做:

var=$(echo $var | grep 'pattern')

这是一种解决思路,将变量内容通过管道传送给 grep ,使用 grep 来完成匹配工作,然后将匹配到的结果赋值给 var。你也可以使用 awk、sed 来替换 grep。为什么需要 echo 一个变量的内容呢?这是因为 awk、sed、grep 不能直接处理变量内容,它们面向文件完成操作。因此这里首先使用 echo 将变量的值输出到管道的另一端,以管道的另一端作为 awk、sed、grep 的输入进行处理就能够得到需要的结果。

实际上,我们可以不借助其它命令,完全使用 bash 提供的 [[ expression ]] 语句的扩展功能来完成我们想要的功能。上面的示例可以修改为如下语句:

	[[ $var =~ pattern ]];
	var=${BASH_REMATCH[0]}

下面是一个具体的示例:

    [longyu@debian:21:03:10] ~ $ filename=$(< filelist)
    [longyu@debian:21:03:20] ~ $ echo $filename
    ./Screenshot from 2018-10-23 20-03-53.png ./Screenshot from 2018-10-22 23-06-20.png
    [longyu@debian:21:03:23] ~ $ [[ $filename =~ ".*from" ]]; echo ${BASH_REMATCH[0]}
    
    [longyu@debian:21:04:08] ~ $ [[ $filename =~ "*from" ]]; echo ${BASH_REMATCH[0]}
    
    [longyu@debian:21:04:19] ~ $ [[ $filename =~ "from" ]]; echo ${BASH_REMATCH[0]}
    from
    [longyu@debian:21:04:22] ~ $ [[ $filename =~ .*from ]]; echo ${BASH_REMATCH[0]}
    ./Screenshot from 2018-10-23 20-03-53.png ./Screenshot from
    [longyu@debian:21:04:32] ~ $ [[ $filename =~ '.*from' ]]; echo ${BASH_REMATCH[0]}
    
    [longyu@debian:21:04:43] ~ $ [[ $filename =~ ".*from" ]]; echo ${BASH_REMATCH[0]}
    
    [longyu@debian:21:04:50] ~ $ pattern=".*from"
    [longyu@debian:21:05:00] ~ $ echo $pattern
    .*from
    [longyu@debian:21:05:04] ~ $ [[ $filename =~ "$pattern" ]]; echo ${BASH_REMATCH[0]}
    
    [longyu@debian:21:05:20] ~ $ [[ $filename =~ $pattern ]]; echo ${BASH_REMATCH[0]}
    ./Screenshot from 2018-10-23 20-03-53.png ./Screenshot from

上面的示例中存在着几个问题。当使用单引号或双引号将 pattern 括起来的时候,括起来的 pattern 将会变为一般字符而非正则表达式元字符,因此匹配不到任何内容。

当我们使用双引号将变量括起来时,在这种环境中 shell 不展开变量,以引号中的内容作为一般字符来匹配,因此也没有匹配到内容。

下面是子组匹配的一个示例:

    [longyu@debian:21:21:19] ~ $ [[ $filename =~ ^\./([A-Z][a-z]*)( ) ]]; echo ${BASH_REMATCH[0]}; echo ${BASH_REMATCH[1]}
    ./Screenshot
    Screenshot
    [longyu@debian:21:21:22] ~ $ [[ $filename =~ '^\./([A-Z][a-z]*)( )' ]]; echo ${BASH_REMATCH[0]}; echo ${BASH_REMATCH[1]}
    
    
    [longyu@debian:21:21:34] ~ $ [[ $filename =~ "^\./([A-Z][a-z]*)( )" ]]; echo ${BASH_REMATCH[0]}; echo ${BASH_REMATCH[1]}

添加引号的问题与上一个例子中的问题相同,更多描述详见 bash 的帮助文档。

需要注意这里使用子组匹配时不需要使用反斜杠对左右括号进行转义,sed 中是需要添加的。

=~ 表示以 pattern 对该操作符左边的展开内容进行匹配,匹配到的结果将放到 BASH_REMATCH 数组中,BASH_REMATCH[0] 表示匹配到的所有内容,BASH_REMATCH[1]–BASH_REMATCH[n] 依次存放匹配到的各个子组。这里没有说 n 的上限,也就不深究了吧。不过需要注意的是在 sed 中确实有明确的限制,一般为 12 吧,我需要查查资料!

需要注意这里的 pattern ,可以直接使用其它变量,这样程序设计变得更加灵活。

这是正则表达式的一个应用之一,借助正则表达式我们可以高效的完成批量任务,既是重点也是难点!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值