2012-03-13 20 views
5

Tôi đang cố gắng đưa ra biểu thức chính quy để xóa nhận xét khỏi câu lệnh SQL.Biểu thức chính quy để xóa nhận xét khỏi câu lệnh SQL

regex này gần như hoạt động:

(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|'(?:[^']|'')*'|(--.*) 

Excepth rằng phần cuối cùng không xử lý "-" ý kiến ​​rất tốt. Vấn đề là xử lý các chuỗi SQL, được phân cách bằng ''.

Ví dụ, nếu tôi có

SELECT ' -- Hello -- ' FROM DUAL 

Nó không phải phù hợp, nhưng nó phù hợp.

Đây là trong ASP/VBScript.

Tôi đã nghĩ về kết hợp từ phải sang trái nhưng tôi không nghĩ rằng công cụ regex của VBScript hỗ trợ nó. Ngoài ra đã cố gắng chơi đùa với vẻ ngoài tiêu cực nhưng kết quả không tốt.

Trả lời

1

Khi bạn nói rằng phần còn lại của regex của bạn là tốt, tôi tập trung vào phần cuối cùng. Tất cả bạn cần làm là xác minh rằng -- là ngay từ đầu và sau đó hãy chắc chắn rằng nó loại bỏ tất cả các dấu gạch ngang nếu có nhiều hơn 2. regex cuối cùng là dưới

(^[--]+) 

Trên đây chỉ là nếu bạn muốn loại bỏ nhận xét bị gạch ngang và không phải toàn bộ dòng. Bạn có thể chạy dưới đây nếu bạn muốn tất cả mọi thứ sau khi nó vào cuối dòng, cũng

(^--.*) 
+0

Hi Justin ... nhờ giúp đỡ. Vẫn còn vấn đề với các bình luận nội tuyến không bắt đầu ngay từ đầu. Giống như CHỌN '- Hello -' TỪ DUAL - nhận xét cần được xóa –

+0

Không vấn đề gì, và chào mừng bạn đến tràn ngăn xếp. Hãy nhớ rằng cách thể hiện sự đánh giá cao ở đây là thông qua các câu trả lời và các câu trả lời được chấp nhận (đánh dấu bên cạnh câu trả lời). Có thể tìm thấy thêm thông tin trong [FAQ], đặc biệt là [FAQ # HowToAsk] Cách hỏi –

4

Trong PHP, tôi đang sử dụng mã này vào SQL bỏ ghi chú:

$sqlComments = '@(([\'"]).*?[^\\\]\2)|((?:\#|--).*?$|/\*(?:[^/*]|/(?!\*)|\*(?!/)|(?R))*\*\/)\s*|(?<=;)\[email protected]'; 
/* Commented version 
$sqlComments = '@ 
    (([\'"]).*?[^\\\]\2) # $1 : Skip single & double quoted expressions 
    |(     # $3 : Match comments 
     (?:\#|--).*?$ # - Single line comments 
     |    # - Multi line (nested) comments 
     /\*    # . comment open marker 
      (?: [^/*] # . non comment-marker characters 
       |/(?!\*) # . ! not a comment open 
       |\*(?!/) # . ! not a comment close 
       |(?R) # . recursive case 
      )*   # . repeat eventually 
     \*\/    # . comment close marker 
    )\s*     # Trim after comments 
    |(?<=;)\s+   # Trim after semi-colon 
    @msx'; 
*/ 
$uncommentedSQL = trim(preg_replace($sqlComments, '$1', $sql)); 
preg_match_all($sqlComments, $sql, $comments); 
$extractedComments = array_filter($comments[ 3 ]); 
var_dump($uncommentedSQL, $extractedComments); 
+0

Đây là sao nhưng tôi không thích trang trí ở cuối, vì nó có thể xóa các dòng mới có thể thực sự mong muốn/cần thiết (như khi một bình luận nội tuyến sau khi mã không có dấu cách trước nó ... mọi người làm điều này: |). Ngoài ra thêm backticks vào danh sách báo giá. Vì vậy, tôi đang sử dụng: $ sqlComments = '@ (([\' "']). *? [^ \\\] \ 2) | ((?: \ # | -). *? $ |/\ * (?: [^/*] |/(?! \ *) | \ * (?! /) | (? R)) * \ * \ /) + @ ms '; – dkloke

+0

Phân đoạn regexp này (php 5.6) hoặc trả về NULL (php 7+) trên các truy vấn có nhận xét dài ngay từ đầu, ví dụ: ' /* đặt ở đây 8kb văn bản giả */ SELECT 1; ' –

+0

Tôi chạy khoảng 120 nghìn truy vấn thông qua regexp này và nó có một số sai sót lớn trong việc phát hiện các nhận xét ở giữa một truy vấn, ví dụ: các chuỗi được đóng gói chứa "-" (chuỗi dấu gạch ngang kép) bị loại bỏ –

1

Mã này công trình cho tôi:

function strip_sqlcomment ($string = '') { 
    $RXSQLComments = '@(--[^\r\n]*)|(\#[^\r\n]*)|(/\*[\w\W]*?(?=\*/)\*/)@ms'; 
    return (($string == '') ? '' : preg_replace($RXSQLComments, '', $string)); 
} 

với một regex chút tinh chỉnh nó có thể được sử dụng để tước bình luận bằng ngôn ngữ nào

0

gốc ly, tôi đã sử dụng giải pháp @Adrien Gibrat. Tuy nhiên, tôi tình cờ gặp một tình huống mà nó không phân tích cú pháp các chuỗi trích dẫn, đúng, nếu tôi có bất cứ thứ gì với một '-' bên trong trước đó. Tôi đã kết thúc bằng văn bản này, thay vào đó:

'[^']*(?!\\)'(*SKIP)(*F)  # Make sure we're not matching inside of quotes 
|(?m-s:\s*(?:\-{2}|\#)[^\n]*$) # Single line comment 
|(?: 
    \/\*.*?\*\/     # Multi-line comment 
    (?(?=(?m-s:\h+$))   # Get trailing whitespace if any exists and only if it's the rest of the line 
    \h+ 
) 
) 

# Modifiers used: 'xs' ('g' can be used as well, but is enabled by default in PHP) 

Xin lưu ý rằng điều này nên được sử dụng khi PCRE có sẵn. Vì vậy, trong trường hợp của tôi, tôi đang sử dụng một biến thể của điều này trong thư viện PHP của tôi.

Example

+1

Điều này thật ngọt ngào! Tôi đã cập nhật regexp để nó bỏ qua các bình luận không chỉ trong các dấu nháy đơn, mà còn cả dấu ngoặc kép và dấu gạch chéo ngược - https://regex101.com/r/GXb0a5/2 –

0

hãy xem câu trả lời của tôi here. Nó hoạt động cả hai cho các dòng chú thích và cho các chú thích khối, thậm chí các chú thích khối lồng nhau. Tôi đoán bạn cần sử dụng regex với nhóm cân bằng, AFAIK không có sẵn trong VBScript.

-1

Đối với tất cả người dùng PHP: vui lòng sử dụng thư viện này - https://github.com/jdorn/sql-formatter. Tôi đã được giao dịch với tước ý kiến ​​từ SQL cho vài năm nay và giải pháp hợp lệ duy nhất sẽ là một máy tokenizer/nhà nước, mà tôi lazily chống lại để viết.Vài ngày trước, tôi phát hiện ra lib này và chạy 120k truy vấn thông qua nó và tìm thấy chỉ có một lỗi (https://github.com/jdorn/sql-formatter/issues/93), được cố định ngay lập tức trong ngã ba của chúng tôi https://github.com/keboola/sql-formatter.

Việc sử dụng rất đơn giản

$query <<<EOF 
/* 
    my comments 
*/ 
SELECT 1; 
EOF; 

$bareQuery = \SqlFormatter::removeComments($query); 
// prints "SELECT 1;" 
print $bareQuery; 
+0

@BaummitAugen Cảm ơn, đã sửa câu trả lời. –

Các vấn đề liên quan