如何在zshell中的关键字处拆分字符串并保存结果?

时间:2015-07-23 17:38:26

标签: linux shell zsh

我是zshell的新手,并尝试使用关键字作为分隔符拆分字符串。输出来自netfilter,并不总是处于固定位置,所以我需要分割我感兴趣的关键词。

我找到了一种有效的方法,但似乎应该有一种更简单的方法。有什么想法吗?

line="[Thu Jul 23 12:29:50 2015] IN=eth0 OUT= SRC=10.1.1.17 DST=10.101.11.1  PROTO=TCP SPT=46286 DPT=1113 SYN URGP=0 "

# this returns a substring starting from 'SRC=' to the end
tmp=${(MS)line##SRC=*}

# use the first element returned in the substring
src=$tmp[(w)1] 

echo "src is $src"

2 个答案:

答案 0 :(得分:0)

您几乎可以将line转换为关联数组,但key=value项似乎过于不规则,因为有时=缺失,有时没有value。因此,一种方法是简单地将整个line拆分为空格并将其放入数组的元素中。目前尚不清楚输出的顺序依赖性如何,但如果你可以指望存在的所需密钥并保持一致的顺序,那么一种方法是:

ary=( ${(s. .)line} )  # split on spaces, storing into array
print $ary[8]
SRC=10.1.1.17

现在您可以通过索引获取任何键值。您也可以使用此数组作为真正的关联数组的起点。

您可能希望先删除日期戳([...])。

答案 1 :(得分:0)

要解析单个关键字,我会使用与=~ conditional operator匹配的正则表达式。

if [[ $line =~ [[:space:]]SRC=[^[:space:]]+ ]]; then
  echo src is $MATCH[6,$#MATCH]
else
  echo >&2 No SRC=
fi

要解析多个关键字,我会使用parameter expansion constructs将字符串减去空格中的时间戳,并将输出存储在关联数组中。

timestamp=${${line%%\]*}##*\[}
typeset -A info
for x in ${=line#*\]}; do
  if [[ $x = *=* ]]; then
    info[${x%%=*}]=${x#*=}
  else
    info[$x]=
  fi
done
echo src is $info[SRC]