OS X 上的 sed - 提取方括号之间的所有文本

OS X 上的 sed - 提取方括号之间的所有文本

鉴于此流:

[foo] 123 [bar]
[gar] dsa [har] 345
[uf] 88 [gc] 43 [br]

我想用 sed (或其他任何东西)来处理这个,所以输出将是:

foo bar
gar har
uf gc br

我试过cat myfile | sed -e 's/^.*\[//;s/\].*$//'

但它仅给我最后一个实例。

我的真实输入是这样的:

53f42d4 [the contacts are duplicated] Adding support in picking email verified users [https://trello.com/c/663]
3c454b0 [the contacts are duplicated] splitting contact by phone numbers and emails and changing contact model to contain only 1 email [https://trello.com/c/663]
0e63e5b [we should not let a user confirm his email if we have a user with this confirmed email already] better doc [https://trello.com/c/643]
02671b7 [we should not let a user confirm his email if we have a user with this confirmed email already] preventing updating email if already in used by other user [https://trello.com/c/643]

所以我想得到第一行:

the contacts are duplicated https://trello.com/c/663

答案1

awk 对此也很有效:使用[ 或者 ]作为字段分隔符,打印每个偶数的场地:

awk -F '[][]' '{for (i=2; i<=NF; i+=2) {printf "%s ", $i}; print ""}' file

使用 sed,我会写

sed -E 's/(^|\])[^[]*($|\[)/ /g' file

答案2

这会将第一个(左)方括号内的任何内容与后面的第一个(右)方括号匹配多次。

$ sed 's/[^[]*\[\([^]]*\)\][^[]*/\1 /g' file
foo bar
gar har
uf gc br

描述:

sed '                      # start a sed script
        s/                 # start a substitute command
        [^[]*              # match all leading characters (except [)
        \[                 # match an explicit [
        \([^]]*\)          # capture text inside brackets.
        \]                 # match the closing ]
        [^[]*              # match trailing text (if any).
        /\1 /              # replace everything matched by the captured text.
        g                  # repeat for all the line.
       ' file              # close script. Apply to file.

这会为每场比赛添加一个尾随空格。如果必须删除,请在末尾添加删除:

sed -e 's/[^[]*\[\([^]]*\)\][^[]*/\1 /g' -e 's/ $//' file

如果您有 GNU grep,这可能会有所帮助(每次捕获一行)。

grep -Po '\[\K[^]]*(?=])'

而且,如果上面的方法不起作用,awk 也可以做到:

awk '{print gensub(/\[([^]]*)\][^[]*/,"\\1 ","g")}' file

答案3

一种惯用的方法是使用环顾断言,请参阅例如https://www.regular-expressions.info/lookaround.html,但 sed 不支持这些,仅在符合 PCRE 的正则表达式处理器中支持。

由于默认情况下 Perl 应该在 macOS 上可用,因此也许这是一个可行的替代方案。

使用 Perl,你可以说

perl -pe 's/.+?(?<=\[)(.+?)(?=\]).+?/$1 /g'

(请注意,这会在行尾添加一个空格)

有关该模式的解释,请参阅https://regexr.com/41gi5

答案4

使用:

sed -n '/\[/ { s-[^[]*--; s-\[\([^]]*\)\][^[]*- \1-g; s- --p }'

算法是:

  • 忽略不包含括号的行。
  • 删除第一个括号之前的文本。
  • 将成对的括号和可选的尾随文本替换为空格,将文本保留在括号内。
  • 删除最初的空格,只保留中间的空格。

相关内容