这是我的情况。目前,我有一个接受两个参数的脚本:书名和章名。例如:
$ myscript book1 chap1
现在,由于需要很长时间才能解释的原因,我希望我的脚本能够采用以下格式的单个参数:{book name}。{chapter name}。例如:
$ myscript book1.chap1
我的困难在于我不知道如何取一个字符串$ 1 = abc.xyz并将其变成两个单独的变量,$ var1 = abc和$ var2 = xyz。我怎么能这样做?
答案 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)
有很多方法可以完成你想要做的事情。其他答案中未涉及的方法之一是pattern substitution。
如果您知道该值将始终在句点上正确分割,则可以对该值应用模式替换,以便使用 IFS 进行标记。例如:
set -- foo.bar
myvar="${1/./ }"
echo $myvar
这将产生foo bar
。