在shell脚本

时间:2016-11-04 11:55:03

标签: regex shell substring

字符串可以是以下形式:

  1. com.company $(PRODUCT_NAME:rfc1034identifier)
  2. $(PRODUCT_BUNDLE_IDENTIFIER)
  3. com.company $(PRODUCT_NAME:rfc1034identifier)$(someRandomVariable)
  4. 我需要帮助编写正则表达式,提取$(..)

    中的所有字符串

    我创建了一个像([(])\w+([)])这样的正则表达式但是当我尝试在shell脚本中执行时,它给出了无法匹配的括号错误。

    这就是我执行的内容:

    echo "com.io.$(sdfsdfdsf)"|grep -P '([(])\w+([)])' -o
    

    我需要获得所有匹配的子串。

3 个答案:

答案 0 :(得分:1)

问题是在echo命令中使用双引号将$(...)解释为command substitution

您可以使用单引号:

echo 'com.io.$(sdfsdfdsf)' | grep -oP '[(]\w+[)]'

这是使用内置BASH正则表达式的替代方法:

$> re='[(][^)]+[)]'
$> [[ 'com.io.$(sdfsdfdsf)' =~ $re ]] && echo "${BASH_REMATCH[0]}"
(sdfsdfdsf)

答案 1 :(得分:1)

使用sed

可以很简单
echo 'com.io.$(asdfasdf)'|sed -e 's/.*(\(.*\))/\1/g'

给出

asdfasdf

对于两个字段:

echo 'com.io.$(asdfasdf).$(ddddd)'|sed -e 's/.*((.*)).$((.*))/\1 \2/g'

给出

asdfasdf ddddd

说明:

sed -e 's/.*(\(.*\))/\1/g'
          \_/\____/  \/
           |    |     |_ print the placeholder content
           |    |___ placeholder selecting the text inside the paratheses
           |____ select the text from beginning including the first paranthese    

答案 2 :(得分:1)

你的问题指明" shell",但不是" bash"。因此,我将从一个基于shell的常见工具(awk)开始,而不是假设您可以使用任何特定的非POSIX内置函数集。

$ cat inp.txt

com.company.$(PRODUCT_NAME:rfc1034identifier)
$(PRODUCT_BUNDLE_IDENTIFIER)
com.company.$(PRODUCT_NAME:rfc1034identifier).$(someRandomVariable)

$ awk -F'[()]' '{for(i=2;i<=NF;i+=2){print $i}}' inp.txt

PRODUCT_NAME:rfc1034identifier
PRODUCT_BUNDLE_IDENTIFIER
PRODUCT_NAME:rfc1034identifier
someRandomVariable

这个awk单线程定义了一个由开始或结束括号组成的字段分隔符。使用这样的字段分隔符,每个偶数字段都将是您要查找的内容,假设所有输入行都已正确格式化并且其他括号内没有括号。

如果您确实想单独在POSIX shell中执行此操作,则可以选择以下选项:

#!/bin/sh

while read line; do
  while expr "$line" : '.*(' >/dev/null; do
    line="${line#*(}"
    echo "${line%%)*}"
  done
done < inp.txt

这将逐步完成每行输入,使用括号将其切片并打印每个切片。请注意,这使用expr,它很可能是外部二进制文件,但至少包含在POSIX.1中。