20

我正在尝试为我编写一个复杂的脚本,我的目标是执行以下操作。我有一个字符串进来,看起来像这样:

2012 2013 "multiple words"

我的目标是将这些中的每一个放在一个由空格分隔的数组中,但仅限于单个单词匹配,而不是那些用双引号括起来的。这些应该被认为是一个词。所以我的想法是分两步完成。首先匹配那些是倍数的单词,从字符串中删除它们,然后在另一个迭代中被空格分割。
不幸的是,我无法找到有关如何echo匹配的帮助。到目前为止,我有这个:

array=$(echo $tags | sed -nE 's/"(.+)"/\1/p')

但这会导致(在 OS X 上):

2012 2013 multiple words

预期结果:

array[1]="2012"
array[2]="2013"
array[3]="multiple words"

我将如何解决这类问题?

谢谢。

4

5 回答 5

20

eval是邪恶的,但这可能是它派上用场的情况之一

str='2012 2013 "multiple words"'
eval x=($str)
echo ${x[2]}
multiple words

或者使用更新版本的bash(在 4.3 上测试)

s='2012 2013 "multiple words"'
declare -a 'a=('"$s"')'
printf "%s\n" "${a[@]}"
2012
2013
multiple words
于 2013-06-27T15:05:45.453 回答
4
$ grep -Eo '"[^"]*"|[^" ]*' <<< '2012 2013 "multiple words"'
2012
2013
"multiple words"

也就是说,打印匹配的字符串

  1. 引号后跟任意数字(甚至零)非引号后跟引号或
  2. 一系列不包含引号或空格的字符。

当然,这不能处理复杂的情况,例如跨多行的引号或转义引号(使用 SQL 之类的双引号或 shell 之类的反斜杠)。

于 2013-06-27T09:22:47.677 回答
2

你可以直接这样做:

arr=(2012 2013 "multiple words")

echo ${#arr[@]} # gives 3
echo ${arr[2]} # gives "multiple words"

编辑:不确定它是否对 OP 有帮助,但以下也将起作用L

str='2012 2013 "multiple\ words"'
read -a arr <<< $str
echo ${#arr[@]} # gives 3
echo ${arr[2]} # gives "multiple words"
于 2013-06-27T09:48:55.713 回答
1

以下将产生您想要的结果:

tags='2012 2013 "multiple words"'
IFS=$'\n'; array=($(echo $tags | egrep -o '"[^"]*"|\S+'))

导致 ZSH:

echo ${array[1]} # 2012
echo ${array[2]} # 2013
echo ${array[3]} # "multiple words"

导致 BASH:

echo ${array[0]} # 2012
echo ${array[1]} # 2013
echo ${array[2]} # "multiple words"

在 OSX 中工作。

于 2013-06-27T14:44:47.890 回答
0

这是一个小的 Python 脚本,用于在尊重引用字段的同时解析空格分隔的 csv:

$ python -c '
import csv, fileinput
for line in csv.reader(fileinput.input(), delimiter=" "):
   for word in line:
      print word
' test.csv
2012
2013
multiple words

由于这使用了 fileinput 模块,因此也可以在管道(或变量中的字符串)中工作:

$ str='2012 2013 "multiple words"'
$ echo $str | python -c '
import csv, fileinput
for line in csv.reader(fileinput.input(), delimiter=" "):
   for word in line:
      print word
' 
2012
2013
multiple words
于 2015-01-22T16:15:17.313 回答