运行数字
此答案适用于任何数量的数字组。示例:
$ echo 'Num123that456are7899900contained0018166intext' \
| sed -En 's/[^0-9]*([0-9]{1,})[^0-9]*/\1 /gp'
123 456 7899900 0018166
扩展答案。
有没有办法告诉 sed 只输出捕获的组?
是的。用捕获组替换所有文本:
$ echo 'Number 123 inside text' \
| sed 's/[^0-9]*\([0-9]\{1,\}\)[^0-9]*/\1/'
123
s/[^0-9]* # several non-digits
\([0-9]\{1,\}\) # followed by one or more digits
[^0-9]* # and followed by more non-digits.
/\1/ # gets replaced only by the digits.
或使用扩展语法(减少反引号并允许使用 +):
$ echo 'Number 123 in text' \
| sed -E 's/[^0-9]*([0-9]+)[^0-9]*/\1/'
123
为避免在没有数字的情况下打印原始文本,请使用:
$ echo 'Number xxx in text' \
| sed -En 's/[^0-9]*([0-9]+)[^0-9]*/\1/p'
- (-n) 默认不打印输入。
- (/p) 仅在替换完成后打印。
并匹配多个数字(并打印它们):
$ echo 'N 123 in 456 text' \
| sed -En 's/[^0-9]*([0-9]+)[^0-9]*/\1 /gp'
123 456
这适用于任何位数的运行:
$ str='Test Num(s) 123 456 7899900 contained as0018166df in text'
$ echo "$str" \
| sed -En 's/[^0-9]*([0-9]{1,})[^0-9]*/\1 /gp'
123 456 7899900 0018166
这与grep命令非常相似:
$ str='Test Num(s) 123 456 7899900 contained as0018166df in text'
$ echo "$str" | grep -Po '\d+'
123
456
7899900
0018166
关于\d
和模式:/([\d]+)/
Sed 无法识别“\d”(快捷方式)语法。 [0-9] 上面使用的 ascii 等价物并不完全等价。唯一的替代解决方案是使用字符类:'[[:digit:]]`。
选择的答案使用这样的“字符类”来构建解决方案:
$ str='This is a sample 123 text and some 987 numbers'
$ echo "$str" | sed -rn 's/[^[:digit:]]*([[:digit:]]+)[^[:digit:]]+([[:digit:]]+)[^[:digit:]]*/\1 \2/p'
该解决方案仅适用于(完全)两个数字运行。
当然,由于答案是在 shell 中执行的,我们可以定义几个变量来缩短答案:
$ str='This is a sample 123 text and some 987 numbers'
$ d=[[:digit:]] D=[^[:digit:]]
$ echo "$str" | sed -rn "s/$D*($d+)$D+($d+)$D*/\1 \2/p"
但是,正如已经解释过的,使用s/…/…/gp 命令更好:
$ str='This is 75577 a sam33ple 123 text and some 987 numbers'
$ d=[[:digit:]] D=[^[:digit:]]
$ echo "$str" | sed -rn "s/$D*($d+)$D*/\1 /gp"
75577 33 123 987
这将涵盖重复的数字运行和编写短(er)命令。