Reputation:
I've been trying to create a sed script that reads a list of phone numbers and only prints ones that match the following schemes:
I'm an absolute beginner, but I tried to write a sed script that would print this for me using the -n -r
flags (the contents of which are as follows):
/\+1\(212\)[0-9]{3}-[0-9]{4}/p
/1\(212\)[0-9]{3}-[0-9]{4}/p
If I run this in sed directly, it works fine (i.e. sed -n -r '/\+1\(212\)[0-9]{3}-[0-9]{4}/p' sample.txt
prints matching lines as expected. This does NOT work in the sed script I wrote, instead sed says:
sed: -e expression #1, char 2: extra characters after command
I could not find a good solution, this error seems to have so many causes and none of the answers I found apply easily here.
EDIT: I ran it with sed -n -r script.sed sample.txt
Upvotes: 1
Views: 4753
Reputation: 46896
Of the various unix tools out there, two use BRE as their default regex dialect. Those two tools are sed
and grep
.
In most operating systems, you can use egrep
or grep -E
to tell that tool to use ERE as its dialect. A smaller (but still significant) number of sed
implementations will accept a -E
option to use ERE.
In BRE mode, however, you can still create atoms with brackets. And you do it by escaping parentheses. That's why your initial expression is failing -- the parentheses are NOT special by default in BRE, but you're MAKING THEM SPECIAL by preceding the characters with backslashes.
The other thing to keep in mind is that if you want sed
to execute a script from a command line argument, you should use the -e
option.
So:
$ cat ph.txt
+1(212)xxx-xxxx
1(212)xxx-xxxx
212-xxx-xxxx
$ grep '^+\{0,1\}1([0-9]\{3\})' ph.txt
+1(212)xxx-xxxx
1(212)xxx-xxxx
$ egrep '^[+]?1\([0-9]{3}\)' ph.txt
+1(212)xxx-xxxx
1(212)xxx-xxxx
$ sed -n -e '/^+\{0,1\}1([0-9]\{3\})/p' ph.txt
+1(212)xxx-xxxx
1(212)xxx-xxxx
$ sed -E -n -e '/^[+]?1\([0-9]{3}\)/p' ph.txt
+1(212)xxx-xxxx
1(212)xxx-xxxx
Depending on your OS, you may be able to get a full list of how this works from man re_format
.
Upvotes: 1
Reputation: 123680
sed
can not automatically determine whether you intended a parameter to be a script file or a script string.
To run a sed script from a file, you have to use -f
:
$ echo 's/hello/goodbye/g' > demo.sed
$ echo "hello world" | sed -f demo.sed
goodbye world
If you neglect the -f
, sed
will try to run the filename as a command, and the d
elete command is not happy to have emo.sed
after it:
$ echo "hello world" | sed demo.sed
sed: -e expression #1, char 2: extra characters after command
Upvotes: 3