在bash脚本中使用regex将1个参数拆分为2个参数

时间:2012-07-10 14:58:08

标签: regex bash

这是我的情况。目前,我有一个接受两个参数的脚本:书名和章名。例如:

$ myscript book1 chap1

现在,由于需要很长时间才能解释的原因,我希望我的脚本能够采用以下格式的单个参数:{book name}。{chapter name}。例如:

$ myscript book1.chap1

我的困难在于我不知道如何取一个字符串$ 1 = abc.xyz并将其变成两个单独的变量,$ var1 = abc和$ var2 = xyz。我怎么能这样做?

6 个答案:

答案 0 :(得分:14)

如果它只是两个标签,你可以使用bash表达式

arg=$1
beforedot=${arg%.*}
afterdot=${arg#*.}

它比cut快,因为它是内置的shell。请注意,这会将 first 最后一个点之前的所有内容放入beforedot,并将所有内容放入afterdot之后。

修改

如果你想用任意数量的标记分割,还有一个替换/重新解释构造:

string=a.b.c.d.e
tokens=(${string//\./ })

您正在用空格替换点,然后由于它周围的括号而被解释为数组声明+定义。

然而,我发现这对于打击兄弟姐妹和后代的可移植性较差。例如,它不适用于我最喜欢的shell zsh

数组需要用大括号取消引用,并从0开始索引:

echo "Third token: ${tokens[2]}"

你也可以通过[@]:

取消引用整个数组来遍历它们
for i in ${tokens[@]}
do
    # do stuff
done

答案 1 :(得分:2)

为了完整性,因为您询问了正则表达式方法:

pattern='^([^.]*)\.(.*)'
[[ $1 =~ $pattern ]]
book=${BASH_REMATCH[1]}
chapter=${BASH_REMATCH[2]}

捕获组是BASH_REMATCH数组中的元素。元素0包含整个匹配。

此正则表达式将捕获第一个元素中的第一个点。在包含后续点的第一个点之后的任何内容都将在第二个元素中。如果需要,可以很容易地修改正则表达式以打破最后一个点。

答案 2 :(得分:1)

如果$arg包含book.chap

read BOOK CHAP<<<$(IFS="."; echo $arg)

将相应地设置变量BOOK和CHAP。这使用bash内部字段分隔符(IFS)来控制bash如何理解单词边界。如果(比方说)您的原始$arg中有多个分隔符,则只需指定其他变量以包含结果。

来自here

  

$ IFS默认为空格(空格,制表符和换行符),但可能是   例如,更改为解析以逗号分隔的数据文件

答案 3 :(得分:0)

您可以使用括号捕捉这两个部分;之后,您可以使用反向引用再次抓取它们。语言之间的语法不同;检查http://www.regular-expressions.info/brackets.html以获取有关反向引用的课程。

答案 4 :(得分:0)

#!/bin/bash

book=${1%.*}
chapter=${1#*.}

printf 'book: %s\nchapter: %s\n' "$book" "$chapter"

答案 5 :(得分:0)

使用Shell参数扩展的模式子进程

有很多方法可以完成你想要做的事情。其他答案中未涉及的方法之一是pattern substitution

如果您知道该值将始终在句点上正确分割,则可以对该值应用模式替换,以便使用 IFS 进行标记。例如:

set -- foo.bar
myvar="${1/./ }"
echo $myvar

这将产生foo bar