使用包含不同模式的sed从文件中删除行

时间:2016-04-19 09:57:02

标签: shell sed

我有来自生产数据库的转储,但我想删除一些表的数据,如messages,messages_files等,因为对本地调试/编程没用。

我一直在使用此命令删除包含此类数据的行:

sed -i '/CREATE DATABASE/d' $current_main_db.sql &&
sed -i '/USE \`okn/d' $current_main_db.sql && 
sed -i '/INSERT INTO \`messages\`/ d' $current_main_db.sql && 
sed -i '/INSERT INTO \`messages_email_cron\`/ d' $current_main_db.sql &&
sed -i '/INSERT INTO \`messages_users\`/ d' $current_main_db.sql &&
sed -i '/INSERT INTO \`messages_files\`/ d' $current_main_db.sql &&
sed -i '/INSERT INTO \`messages_mail_list\`/ d' $current_main_db.sql &&
sed -i '/INSERT INTO \`messages_sms_cron\`/ d' $current_main_db.sql &&
sed -i '/INSERT INTO \`messages_tags\`/ d' $current_main_db.sql &&
sed -i '/INSERT INTO \`messages_temp_receivers\`/ d' $current_main_db.sql &&
sed -i '/INSERT INTO \`messages_threads\`/ d' $current_main_db.sql;

它运行良好,但速度非常慢,所以我尝试将所有模式组合成一个sed命令。我阅读了手册并找到了:

  

regexp1 \ | regexp2

     

匹配regexp1或regexp2。使用括号来使用复杂的替代正则表达式。匹配过程依次从左到右尝试每个替代,并使用成功的第一个替代。它是GNU扩展。

所以我试过这个:

sed -i '/CREATE DATABASE\|USE \`okn\|INSERT INTO \`messages\`\|INSERT INTO \`messages_email_cron\`\|INSERT INTO \`messages_users\`\|INSERT INTO \`messages_files\`\|INSERT INTO \`messages_mail_list\`\|INSERT INTO \`messages_sms_cron\`\|INSERT INTO \`messages_tags\`\|INSERT INTO \`messages_temp_receivers\`\|INSERT INTO \`messages_threads\`/ d' $current_main_db.sql;

但是不行,我试图在没有任何运气的情况下使用括号:

sed -i '/(CREATE DATABASE\|USE \`okn)\|(INSERT INTO \`messages\`)\|(INSERT INTO \`messages_email_cron\`)\|(INSERT INTO \`messages_users\`)\|(INSERT INTO \`messages_files\`)\|(INSERT INTO \`messages_mail_list\`)\|(INSERT INTO \`messages_sms_cron\`)\|(INSERT INTO \`messages_tags\`)\|(INSERT INTO \`messages_temp_receivers\`)\|(INSERT INTO \`messages_threads\`)/d'

我做错了吗?

我搜索SO并找到一些类似的问题,但不适合我。

3 个答案:

答案 0 :(得分:1)

grep应该足够了:

grep -vE '^(INSERT INTO `messages(_email_cron|_users|_files|_mail_list|_sms_cron|_tags|_temp_receivers|_threads)`|CREATE DATABASE|USE `okn)' file

答案 1 :(得分:1)

也可以逃避括号:

sed -i '/\(CREATE DATABASE\)\|\(USE \`okn\)\|\(INSERT INTO \`messages\`\)\|\(INSERT INTO \`messages_email_cron\`\)\|\(INSERT INTO \`messages_users\`\)\|\(INSERT INTO \`messages_files\`\)\|\(INSERT INTO \`messages_mail_list\`\)\|\(INSERT INTO \`messages_sms_cron\`\)\|\(INSERT INTO \`messages_tags\`\)\|\(INSERT INTO \`messages_temp_receivers\`\)\|\(INSERT INTO \`messages_threads\`\)/d'

答案 2 :(得分:1)

您的尝试很慢,因为您为每个命令启动了一个新的sed实例。你的正则表达式很复杂,因为你试图一次处理所有表达式。然而,有一个妥协的解决方案

sed '/pattern1/d; /pattern2/d; ...'

另请注意,您可以简化正则表达式,如@CasimirEtHippolyte所示。