在 shell(不是 Bash)中,我有一个像这样的字符串,我想解析:
stringhere/morestring!99
解析后,我想保留99
末尾的 ,并丢弃字符串的其余部分。
需要保留的子字符串并不总是两个字符长。它将是从 到!
字符串末尾的一个或多个数字,或者是,
。
输入/输出示例:
In: stringhere/morestring!99
Out: 99
In: string/more!99,string/more!98,string/more!97
Out: 99
cut
听起来像是显而易见的东西,除了!
字符串中间的 。
是否有捷径可寻?会awk
更好?
答案1
如果该字符串位于 FILE 中,并且您始终只需要第一个之后!
和之前的第一个数字,
,如果存在,则应该可以工作
awk -F'[!,]' '{print$2}' FILE
它采用!
或,
作为分隔符并显示第二个字段,该字段将是 和 之间的第一个数字!
,,
或紧随其后!
,
如果该行中或之前没有。
,
如果之前有第一个!
上面的 awk 示例,则不适用。
您还可以将一个cut
命令通过管道传输到另一个命令,首先指定!
为分隔符并在第一个命令之后获取内容!
,然后在第二个命令中指定,
为分隔符并在第一个命令之前获取内容(,
如果存在)
cut -d'!' -f2 FILE | cut -d',' -f1
答案2
您可以使用cut
,但需要两次通过。第一个将获取第一个之后的内容!
,第二个将删除之后的任何内容,
:
$ echo 'string/more!99,string/more!98,string/more!97' |
cut -d'!' -f2- | cut -d, -f1
99
同样,对于您没有的情况(这里不需要,
第二个,我添加它只是为了表明您可以使用完全相同的命令):cut
$ echo 'string/more!99' | cut -d'!' -f2- | cut -d, -f1
99
另一种选择是sed
:
$ echo 'string/more!99,string/more!98,string/more!97' |
sed -E 's/^[^!]+!([0-9]+).*/\1/'
99
$ echo 'string/more!99' | sed -E 's/^[^!]+!([0-9]+).*/\1/'
99
或者perl
:
$ echo 'string/more!99,string/more!98,string/more!97' |
perl -pe 's/.+?!(\d+).*/\1/'
99
$ echo 'string/more!99' | perl -pe 's/.+?!(\d+).*/\1/'
99
或者GNUgrep
$ echo 'string/more!99,string/more!98,string/more!97' |
grep -oP '^[^!]+!\K\d+'
99
$ echo 'string/more!99' | grep -oP '^[^!]+!\K\d+'
99
答案3
您所需要的只是 shell 的参数扩展语法:这是在短跑
$ input='stringhere/morestring!99'
$ echo "${input#*!}"
99
后面#
跟着一个模式:最短 字首匹配该模式将被删除。
$ input='string/more!99,string/more!98,string/more!97'
$ first=${input%%,*}
$ echo "${first#*!}"
99
后面%%
跟着一个模式:最长 后缀匹配的模式被删除。
${var#pattern)
-- 删除最短匹配前缀。
${var##pattern)
-- 删除最长匹配前缀。
${var%pattern)
-- 删除最短匹配后缀。
${var%%pattern)
-- 删除最长匹配后缀。
答案4
您也可以使用sed
.使用 GNUsed
并打开扩展正则表达式:
sed -E 's/^[^!]*!([0-9]+).*$/\1/'
或者 - 更便携:
sed 's/^[^!]*!\([0-9]\{1,\}\).*$/\1/p'
这将匹配模式“第一个之前的任何内容!
,后跟一个或多个数字,之后可能是任何类型的字符,直到行尾”,并仅用“一个或多个数字”部分替换整行。
~> echo 'string/more!99,string/more!98,string/more!97' | sed -E 's/^[^!]*!([0-9]+).*$/\1/'
99
如果存在不匹配的行,您可以使用以下命令抑制它们
sed -nE 's/^[^!]*!([0-9]+).*$/\1/p'
反而。默认情况下,这不会输出任何内容,并且仅在找到匹配模式时才打印输出。