使用Bash将两个字符之间的所有字符串提取到数组

时间:2018-04-18 14:48:25

标签: linux bash awk sed grep

我搜索了我们的但是找不到使用Bash将两个字符之间的所有字符串提取到数组的解决方案。

我找到了

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Dialog dialog = super.onCreateDialog(savedInstanceState);
    dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
    return dialog;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(getLayoutId(), container, false);
}



@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    Dialog dialog = getDialog();
    if (dialog != null) {
            dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
            dialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
        }
    }
}

但这只是向我展示了最后一个条目。

My String看起来像:

sed -n 's/.*\[\(.*\)\].*/\1/p'

我想要一个像这样的数组:

var="[a1] [b1] [123] [Text text] [0x0]"

所以我在[和]之间搜索Stings并将其加载到没有[和]的数组中。

感谢您的帮助!

4 个答案:

答案 0 :(得分:3)

没有简单的方法可以做到这一点。我会使用一个循环一次一个地提取它们:

var="[a1] [b1] [123] [Text text] [0x0]"
regex='\[([^]]*)\](.*)'
while [[ $var =~ $regex ]]; do
  arr+=("${BASH_REMATCH[1]}")
  var=${BASH_REMATCH[2]}
done

在正则表达式中,\[([^]]*)\]会在第一个[之后捕获所有内容(但不包括)下一个](.*)在下一次迭代后捕获所有内容。

您可以在declare -n 4.3或更高版本中使用bash,使其看起来不那么令人生畏。

declare -n m1=BASH_REMATCH[1] m2=BASH_REMATCH[2]
regex='\[([^]]*)\](.*)'

var="[a1] [b1] [123] [Text text] [0x0]"
while [[ $var =~ $regex ]]; do
  arr+=("$m1")
  var=$m2
done

答案 1 :(得分:0)

$ IFS=, arr=($(sed 's/\] \[/","/g;s/\]/"/;s/\[/"/' <<< "$var")); echo "${arr[3]}"

"Text text"

答案 2 :(得分:-1)

使用GNU awk进行多字符RS和RT以及更新版本的bash for mapfile:

$ mapfile -t arr < <(echo "$var" | awk -v RS='[^][]+' 'NR%2{print RT}')

$ declare -p arr
declare -a arr=([0]="a1" [1]="b1" [2]="123" [3]="Text text" [4]="0x0")

答案 3 :(得分:-1)

这里有很多可能适合您的建议,但可能不会取决于您的数据。例如,将] [的当前字段分隔符替换为逗号,除非您的字段中嵌入了逗号。您的样本数据没有,但一个人不知道。 :)

理想的解决方案是使用某些东西作为字段分隔符,保证永远不会成为字段的一部分,如null。但这很难以便携方式进行(即不知道有哪些工具可用)。因此,不太极端的立场可能是使用换行符作为分隔符:

var="[a1] [b1] [123] [Text text] [0x0]"

mapfile -t arr < <(sed $'s/^\[//;s/] \[/\\\n/g;s/]$//' <<<"$var")

declare -p arr

会导致:

declare -a arr='([0]="a1" [1]="b1" [2]="123" [3]="Text text" [4]="0x0")'

这在功能上等同于Inian提供的awk解决方案。请注意,mapfile需要bash版本4或更高版本。

那就是说,你也可以只在bash中使用它,而不依赖于像sed这样的任何外部工具:

arr=( $var )

last=0
for i in "${!arr[@]}"; do
  if [[ ${arr[$i]} != \[* ]]; then
    arr[$last]="${arr[$last]} ${arr[$i]}"
    unset arr[$i] 
    continue
  fi
  last=$i
done

for i in "${!arr[@]}"; do
  arr[$i]="${arr[$i]:1:$((${#arr[$i]}-2))}"
done

此时,declare -p arr会导致:

declare -a arr='([0]="a1" [1]="b1" [2]="123" [3]="Text text" [5]="0x0")'

这会将您的$var吸入数组$arr[],其字段由空格分隔,然后根据字段是否以方括号开头折叠字段。然后它遍历字段并用消除第一个和最后一个字符的子字符串替换它们。它可能会有一点弹性和难以阅读,但它都在bash中。 :)