我需要删除所有不是 4 个字符的数字,例如9838
、6738
或。1337
1889
我认为这个命令会起作用:
sed 's/....[^0-9]//g'
.
表示正则表达式中的任何字符,并且[^0-9]
不删除任何数字。
这是一个输入示例:
9228 Hello 8473 World War 1 1914-1918 Hello 8391 World War 2 1939-1945
将会:
9228 8473 1914 1918 8391 1939 1945
答案1
我可以用grep
命令回答:
输入文件:
9228 Hello 8473 World War 1 1914-1918 Hello 8391 World War 2 1939-1945
命令:
grep -Eo '\<[0-9]{4}\>' file |tr '\n' ' '
返回任意长度为 4 的数字。
-E
切换到扩展正则
-o
表达式仅打印匹配部分
输出:
9228 8473 1914 1918 8391 1939 1945
更新答案:
输入文件:
9228 Hello 8473 World War 1 1914-1918 Hello 8391 World War 2 1939-1945
foo1234bar
a1111
12345
0x2222ff
1.3333
2.54321
命令
grep -oP '(?<![0-9])[0-9]{4}(?![0-9])' file | tr '\n' ' '
grep 带有负向后查找/向前查找:
(?<![0-9])[0-9]{4}
(负向后查找):将数字匹配到 length=4 且前面没有数字[0-9]
。
[0-9]{4}(?![0-9])
(负向前视):将数字匹配到长度=4,后面不跟数字。
输出:
9228 8473 1914 1918 8391 1939 1945 1234 1111 2222 3333
答案2
您可以使用perl
。
perl -nle'print join " ", /(?<![0-9])[0-9]{4}(?![0-9])/g'
这也适用于多行输入,因此如果您有:
9228 Hello 8473 World War 1 1914-1918
Hello 8391 World War 2 1939-1945
您将得到以下返回信息:
9228 8473 1914 1918
8391 1939 1945
(-0777
如果您希望数字位于同一行,请添加。)
答案3
POSIXly:
< file tr -cs 0-9 '[\n*]' | grep -xE '.{4}' | paste -sd ' ' -
答案4
使用单个反斜杠,s///
您可以在 POSIX 中执行此操作sed
- 但有很多反斜杠:
sed 's/[^0-9]*\([0-9]\{5,\}\)*[^0-9]*\([0-9]\{4\}\)*.\{0,1\}/ \2/g
' <<\IN
92828 Hello 8473 World War 1 1914-1918 Hello 8391 World War 2 1939-1945
IN
输出
8473 1914 1918 8391 1939 1945
它g
首先吞噬所有具有 5 个或更多数字的序列 - 然后是任何^
非数字 -然后您的匹配项,以及任何其他字符的最后 0 或 1。在整个语句中,仅保存了 1 个表达式 - 您的匹配项 - 因此,除了任何中间的空白之外,这就是剩下的内容。
但通过一点翻译,事情就会变得更容易:
sed 'y/ /./;s/[0-9]\{4,\}/ & /g;s/\( [^ ]\{4\} \)*[^ ]*/\1/g
' <<\IN
92828 Hello 8473 World War 1 1914-1918 Hello 8391 World War 2 1939-1945
IN
输出
8473 1914 1918 8391 1939 1945
sed
首先将所有空格音译为点。接下来,它将任何 4 个或更多数字的序列包裹在空格中。最后,它删除所有非空格字符,保存任何由空格包围的四个字符序列。