Text-Processing
如何提取 SQL 語句的一部分以進行搜尋和替換?
我正在使用 bash shell 嘗試進行搜尋和替換。我有一個看起來像的行文件
... INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '฿'); ...
我想將每一行轉換為
currency = Currency.find_by_iso('THB') || Currency.new(:code => 'THB')
如您所見,我從 INSERT SQL 命令中提取了第二個參數。我以為我能做到
perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES ('(.*?)', '(.*?)', '(.*?)');/currency = Currency.find_by_iso(\$&) || Currency.new(:code => '\$&')/" currencies.rb
但什麼都沒有發生——也就是說,替換的輸出使行保持不變。如何從我的 SQL 語句中擷取第二個值並從中創建一個新行?
替換的輸出使行保持不變
這表明您的正則表達式與輸入不匹配,因此讓我們退後一步,看看我們是否可以獲得一個有效的最小正則表達式:
perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES ('(.*?)', '(.*?)', '(.*?)');//" currencies.rb > INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');
簡單地刪除替換,不出所料,你第一次得到的沒有什麼不同,它與輸入不匹配。
現在您的正則表達式的最後一部分
('(.*?)', '(.*?)', '(.*?)')
包含在正則表達式中具有特殊含義的字元分配,所以讓我們刪除它們,看看是否有效:perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES .*;//" currencies.rb > INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');
仍然不匹配,現在唯一的特殊字元是
()
可能應該被轉義的:perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES .*;//" currencies.rb >
是的,匹配 - 我們的輸入被匹配並刪除,所以讓我們再次添加結束位,這一次也轉義其他
()
s :perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);//" currencies.rb >
仍然匹配,所以讓我們再次添加替換:
perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);/currency = Currency.find_by_iso(\$&) || Currency.new(:code => '\$&')/" currencies.rb > currency = Currency.find_by_iso(INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');) || Currency.new(:code => 'INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');')
嗯,似乎是匹配錯誤的部分。這是因為 & 被整個匹配的表達式代替,而不是你想要的單個子組
$1
,$2
等等:perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);/currency = Currency.find_by_iso(\$2) || Currency.new(:code => '\$2')/" currencies.rb > currency = Currency.find_by_iso(THB) || Currency.new(:code => 'THB')
幾乎在那裡,缺少一些引號 - 我們也不需要其他兩個子組匹配,所以讓我們刪除它們:
perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('.*?', '(.*?)', '.*?'\);/currency = Currency.find_by_iso('\$1') || Currency.new(:code => '\$1')/" currencies.rb > currency = Currency.find_by_iso('THB') || Currency.new(:code => 'THB')
我們去了,正是我們想要的。
當面對似乎不起作用的複雜正則表達式時,通常是一些特殊字元的問題,它因語言和工具而異 - 有時需要轉義,有時不需要。從用更簡單的替代方案去除這些字元開始總是有幫助的,直到你得到一個匹配你輸入的一部分的正則表達式,即使它不完全是你想要的部分 - 然後將它從那裡一點一點地展開,直到它中斷或你得到你想要的。如果您發現它打破了這一點,您應該閱讀您正在使用的語言/工具的文件,以找出您實際正在尋找的語法。