Reputation: 11977
I'm trying to convert the following (MS-SQL) string
INSERT INTO Foo (Bar) VALUES (CAST('1958-08-22 21:00:00.000' AS DateTime))
to SQLite syntax
INSERT INTO Foo (Bar) VALUES (-358491600)
I'm successfully doing this with the following sed
arguments:
sed -r "s#cast\('(.*)' as datetime\)#date -d '\1' '+%s'#ige"
(calling date -d '...' '+%s'
to convert the date to epoch)
Running the same command over the complete line:
echo "INSERT INTO Foo (Bar) values (cast('1958-08-22 21:00:00.000' as datetime))" | \
sed -r "s#cast\('(.*)' as datetime\)#date -d '\1' '+%s'#ige"
...produces an error: sh: 1: Syntax error: "(" unexpected
From what I've tracked, parenthesis cause the line to fail:
echo "() cast('1958-08-22 21:00:00.000' as datetime)" | \
sed -r "s#cast\('(.*)' as datetime\)#date -d '\1' '+%s'#ige"
Removing the e
switch properly converts the command. What am I doing wrong?
Upvotes: 1
Views: 452
Reputation: 195249
this sed with ge
flag does your job:
sed -r 's/(.*CAST[^\x27]*\x27)([^\x27]*)(\x27 AS DateTime.*)/
echo "\1"$(date -d"\2" "+%s")"\3"/ge' file
with your example:
kent$ cat f
INSERT INTO Foo (Bar) VALUES (CAST('1958-08-22 21:00:00.000' AS DateTime));
INSERT INTO Foo (Bar) VALUES (CAST('1958-08-23 22:00:00.000' AS DateTime));
kent$ sed -r 's/(.*CAST[^\x27]*\x27)([^\x27]*)(\x27 AS DateTime.*)/echo "\1"$(date -d"\2" "+%s")"\3"/ge' file
INSERT INTO Foo (Bar) VALUES (CAST('-358488000' AS DateTime));
INSERT INTO Foo (Bar) VALUES (CAST('-358398000' AS DateTime));
if you don't want to have the As DateTime
in output, just make proper groups, I think you can manage it.
Upvotes: 2
Reputation: 15214
If you run your command under strace
to see what exacly will be executed you will see the following:
$ echo "INSERT INTO Foo (Bar) values (cast('1958-08-22 21:00:00.000' as datetime))" | strace -ff sed -r "s#cast\('(.*)' as datetime\)#date -d '\1' '+%s'#ige" 2>&1 | grep 'execve('
execve("/bin/sed", ["sed", "-r", "s#cast\\('(.*)' as datetime\\)#dat"...], [/* 27 vars */]) = 0
[pid 8179] execve("/bin/sh", ["sh", "-c", "INSERT INTO Foo (Bar) values (da"...], [/* 27 vars */] <unfinished ...>
It means that sed
tries to execute not only text that was matched the pattern but the whole line.. So, probably, you can't do that with sed
(I will be glad if I'm mistaken.)
So, I suggest to gather all dates from file, convert them and then replace one by one. For example:
$ cat q.sql
INSERT INTO Foo (Bar) VALUES (CAST('1958-08-22 21:00:00.000' AS DateTime));
INSERT INTO Foo (Bar) VALUES (CAST('1958-08-23 22:00:00.000' AS DateTime));
$ sed "s|.*CAST('\([^']\+\)'.*|\1|" q.sql | while read DATE; do sed -i "s|$DATE|$(date -d "$DATE" '+%s')|" q.sql; done
$ cat q.sql
INSERT INTO Foo (Bar) VALUES (CAST('-358495200' AS DateTime));
INSERT INTO Foo (Bar) VALUES (CAST('-358405200' AS DateTime));
Upvotes: 2