I want to store a specific part of a matched result as a variable to be used for replacement later. I would like to keep this in a one liner instead of finding the variable I need before hand.
when configuring apache, and use mod_rewrite, you can specificy specific parts of patterns to be used as variables,like this:
RewriteRule ^www.example.com/page/(.*)$ http://www.example.com/page.php?page=$1 [R=301,L]
the part of the pattern match that's contained inside the parenthesis is stored as $1 for use later. So if the url was www.example.com/page/home
, it would be replaced with www.example.com/page.php?page=home
. So the "home" part of the match was saved in $1 because it was the part of the pattern inside the parenthesis.
I want something like this functionality with a sed
command, I need to automatically replace many strings in a SQL dump file, to add drop table if exist commands before each create table, but I need to know the table name to do this, so if the dump file contains something like:
...
CREATE TABLE `orders`
...
I need to run something like:
cat dump.sql | sed "s/CREATE TABLE `(.*)`/DROP TABLE IF EXISTS $1\N CREATE TABLE `$1`/g"
to get the result of:
...
DROP TABLE IF EXISTS `orders`
CREATE TABLE `orders`
...
I'm using the mod_rewrite syntax in the sed
command as a logical example of what I'm trying to do.
Any suggestions?
The shell is responsible for expanding variables. When you use single quotes for strings, its contents will be treated literally, so sed now tries to replace every occurrence of the literal $var1 by ZZ .
It means that sed will read the next line and start processing it. Your test script doesn't do what you think. It matches the empty lines and applies the delete command to them.
In some versions of sed, the expression must be preceded by -e to indicate that an expression follows. The s stands for substitute, while the g stands for global, which means that all matching occurrences in the line would be replaced.
You can tell sed to carry out multiple operations by just repeating -e (or -f if your script is in a file). sed -i -e 's/a/b/g' -e 's/b/d/g' file makes both changes in the single file named file , in-place.
sed '/CREATE TABLE \([^ ]*\)/ s//DROP TABLE IF EXISTS \1; &/'
Find a CREATE TABLE statement and capture the table name. Replace it with 'DROP TABLE IF EXISTS' and the table name, plus a semi-colon to terminate the statement, and a copy of what was matched to preserve the CREATE TABLE statement.
This is classic sed
notation. Since you're using bash
, there's a chance you're using GNU sed
and will need to add --posix
to use that notation, or you'll need to fettle the script to use GNU's non-standard sed
regexes. I've also not attempted to insert a newline into the output. You can do that with GNU sed
if it is important enough to you.
The key points are the parentheses (classically needing to be escaped with a backslash) are the capture mechanism, and backslash-number is the replacement mechanism.
sed -r "s/CREATE TABLE (\`.*\`)/DROP TABLE IF EXISTS \1\n &/g" dump.sql
test:
kent$ cat t.txt
CREATE TABLE `orders`
...
CREATE TABLE `foo`
...
...
CREATE TABLE `bar`
...
kent$ sed -r "s/CREATE TABLE (\`.*\`)/DROP TABLE IF EXISTS \1\n &/g" t.txt
DROP TABLE IF EXISTS `orders`
CREATE TABLE `orders`
...
DROP TABLE IF EXISTS `foo`
CREATE TABLE `foo`
...
...
DROP TABLE IF EXISTS `bar`
CREATE TABLE `bar`
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With