Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 我需要一个sed命令将电话号码格式从999-999-9999更改为(999)999-9999_Unix_Sed - Fatal编程技术网

Unix 我需要一个sed命令将电话号码格式从999-999-9999更改为(999)999-9999

Unix 我需要一个sed命令将电话号码格式从999-999-9999更改为(999)999-9999,unix,sed,Unix,Sed,我需要一个sed命令将电话号码格式从999-999-9999更改为(999)999-9999。 以下是我一直在尝试的: sed 's/[[:digit:]]\-[[:digit:]]\-[[:digit:]]/\([[:digit:]]\)[[:digit:]]\-[[:digit:]]/gp' 我也试过: sed 's/([0-9]{3})\-([0-9]{3})\-([0-9]{4})/\(([0-9]{3}\))([0-9]{3})\-([0-9]{4})/gp' 符号[[:digi

我需要一个sed命令将电话号码格式从
999-999-9999
更改为
(999)999-9999
。 以下是我一直在尝试的:

sed 's/[[:digit:]]\-[[:digit:]]\-[[:digit:]]/\([[:digit:]]\)[[:digit:]]\-[[:digit:]]/gp' 
我也试过:

sed 's/([0-9]{3})\-([0-9]{3})\-([0-9]{4})/\(([0-9]{3}\))([0-9]{3})\-([0-9]{4})/gp'

符号
[[:digit:]
与单个数字匹配;您需要匹配重复的数字,这是通过将重复计数包装在
\{3\}
中来实现的(对于固定计数,也有可变的计数范围,但它们在这里不相关,
*
等等)。您需要在
\(…\)
中捕获匹配的内容,以便在替换中引用它们。在替换中,使用
\1
等引用捕获的片段。捕获按
\(
符号)的顺序从左到右编号

sed 's/\([[:digit:]]\{3\}\)-\([[:digit:]]\{3\}-[[:digit:]]\{4\}\)/(\1)\2/g' 
或:

这是经典的
sed
表示法;您也可以找到使用扩展正则表达式的变体,但与此表示法不同,您需要根据平台使用不同的选项。模式查找3位数字(第一个捕获)、一个破折号,然后再查找3位数字、另一个破折号和4位数字作为第二个捕获,并将所有这些替换为开括号(美式括号),前3位为右括号,其余3位为破折号,4位为右括号

BSD(Mac OS X):

GNU:

请注意,所有这些正则表达式都将转换为

9876-345-54321
致:

修复不那么琐碎的问题,尤其是在
sed
中。使用Perl:

$ echo "987-654-3210 and 2987-654-543210 and 222-333-4444 and 543-432-5544" |
> perl -p -e 's/\b([0-9]{3})-([0-9]{3}-[0-9]{4})\b/(\1)\2/g'
(987)654-3210 and 2987-654-543210 and (222)333-4444 and (543)432-5544
$
\b
在PCRE中标记了一个单词边界。这意味着Perl不匹配
a222-333-4444
;您可以改进内容,使其在匹配字符串之前坚持非数字或字符串开头,在匹配字符串之后坚持非数字或字符串结尾

$ echo "987-654-3210 and 2987-654-543210 and a222-333-4444 and 543-432-5544" |
> perl -p -e 's/(^|\D)([0-9]{3})-([0-9]{3}-[0-9]{4})(\D|$)/\1(\2)\3\4/g' 
(987)654-3210 and 2987-654-543210 and a(222)333-4444 and (543)432-5544
$
或使用(BSD或GNU)
sed
扩展正则表达式(显示BSD):

请注意,如果愿意,可以编写求反的数字字符类表示法


迭代开发很有帮助。

单元匹配的是一位数字,而不是三位数字。为什么不使用
awk
?@hek2mgl:因为问题询问的是
sed
(通过标签,并通过说明已尝试的内容)。我不认为
awk
在这里提供了很大的优势;使用
gsub
或等效物是可行的,但如果有什么符号比
sed
更笨拙的话。我认为这是个笑话。@JonathanLeffler是的,这确实是个笑话:)@hek2mgl:对不起,我错过了问题结尾的笑声。太棒了,谢谢!!你能解释一下这个部分到底在做什么吗,(\1)\2/?在第一个变体中,
\(…\)
“捕获”了匹配的部分。在替换中,你可以根据需要经常引用这些捕获的片段(这里,每个片段一次)使用
\1
等引用片段。片段按
\(
符号出现的顺序进行索引。因此,
(\1)\2
将数字短划线字符串替换为一个开括号、第一个3位数组、一个闭括号和第二个捕获的字符串(999-9999)。感谢所有帮助!
sed -r 's/([0-9]{3})-([0-9]{3}-[0-9]{4})/(\1)\2/g'
9876-345-54321
9(876)345-54321
$ echo "987-654-3210 and 2987-654-543210 and 222-333-4444 and 543-432-5544" |
> perl -p -e 's/\b([0-9]{3})-([0-9]{3}-[0-9]{4})\b/(\1)\2/g'
(987)654-3210 and 2987-654-543210 and (222)333-4444 and (543)432-5544
$
$ echo "987-654-3210 and 2987-654-543210 and a222-333-4444 and 543-432-5544" |
> perl -p -e 's/(^|\D)([0-9]{3})-([0-9]{3}-[0-9]{4})(\D|$)/\1(\2)\3\4/g' 
(987)654-3210 and 2987-654-543210 and a(222)333-4444 and (543)432-5544
$
$ echo "987-654-3210 and 2987-654-543210 and a222-333-4444 and 543-432-5544" |
> sed -E 's/(^|[^0-9])([0-9]{3})-([0-9]{3}-[0-9]{4})([^0-9]|$)/\1(\2)\3\4/g'
(987)654-3210 and 2987-654-543210 and a(222)333-4444 and (543)432-5544
$