我的bash代码仅转储表的特定行:
acc_db mydb -c "create table export_table as $1"
mypg_dump -d mydb -a -t export_table --data-only --column-inserts >> /tmp/export_data.sql
acc_db mydb -c "drop table export_table"
sed -i -e 's/export_table/'$table'/g' /tmp/export_data.sql
# where :
# $1 contains my SELECT statement
# $table is the actual name of the table I'm interest in
# acc_db is a wrapper to override the pwd insert
# mydb is ... some db
首先,我曾经在mypg_dump行上使用grep来仅获取INSERT语句-但是由于我发现多行字段被grep掉了,破坏了sql语句,所以我不得不更改它。但是现在我有这种输出:
-- some comment
-- comment
*blank lines*
*various SET statements*
*SELECT statements*
INSERT [...]
-- some comments
*more blank lines*
我真正需要的只是INSERT语句,但是我找不到任何只获取插入内容的方法。
如果要获取多行插入,则需要使用比grep更灵活的方法。使用perl单线的示例:
perl -wlne 'if (!$current_statement){if (/^\s*INSERT/){if (/;\s*$/) {push @inserts, $_} else {s/\r//g;$current_statement = $_}}} else {$current_statement .= $_;if (/;\s*$/){push @inserts, $current_statement;$current_statement = "";}}}{print for (@inserts)' /tmp/export_data.sql > /tmp/insert_data.sql
正在发生的故障:
# - w: use warnings
# - l: loop through input storing each line's contents in $_
# - n: don't print the line after processing
# - e: execute one liner
if (!$current_statement) { # if not in multi-line insert
if (/^\s*INSERT/) { # skip if it's not an INSERT statement
if (/;\s*$/){ # single line insert, push to list
push @inserts, $_
} else { # multi-line insert strip off CR, save line and continue
s/\r//g;
$current_statement = $_
}
}
} else { # continue an multi-line existing multi-line insert
$current_statement .= $_; # always append the statement
if (/;\s*$/){ # if finished, push to @inserts, reset variable
push @inserts, $current_statement;
$current_statement = "";
}
}
}{ # "eskimo kiss": finishes the loop from -n, runs code after processing the files
print for (@inserts) # print each entry of the inserts array