Chỉ xóa dấu phẩy trong dấu ngoặc kép


10

Trong một tệp văn bản, tôi muốn xóa ,(dấu phẩy) và cả "dấu ngoặc kép (chỉ khi dấu ngoặc kép chứa các số được phân tách bằng dấu phẩy).

56,72,"12,34,54",x,y,"foo,a,b,bar"

Dự kiến

56,72,123454,x,y,"foo,a,b,bar"

Lưu ý: Tôi hiển thị dòng trên chỉ là một ví dụ. Tệp văn bản của tôi chứa nhiều dòng như trên và các số được phân tách bằng dấu phẩy có trong dấu ngoặc kép sẽ khác nhau. Đó là,

56,72,"12,34,54",x,y,"foo,a,b,bar"
56,92,"12,34",x,y,"foo,a,b,bar"
56,72,"12,34,54,78,76,54,67",x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar","12,34,54"
56,72,x,y,"foo,a,b,bar","12,34,54","45,57,84,92","bar,foo"

Sản lượng dự kiến:

56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"

Có một nsố số hiện diện trong dấu ngoặc kép được phân tách bằng dấu phẩy. Và cũng để lại dấu ngoặc kép có chứa các ký tự như nó là.

Tôi yêu sedcông cụ xử lý văn bản. Tôi rất vui nếu bạn đăng bất kỳ sedgiải pháp cho việc này.


Từ 56,72,"12,34,54",x,y,"foo,a,b,bar"đến 56,72,123454,x,y,"a,b", foobarđang biến mất. Đó có phải là đầu ra mong muốn của bạn?
cuonglm

Ví dụ bạn sử dụng hơi khó hiểu vì một số thành phần (như foobar) được xóa cùng với dấu phẩy. Hơn nữa, một số trích dẫn biến mất nơi những người khác vẫn còn. Chưa kể rằng dấu phẩy giữa abvẫn còn. Có bất kỳ mô hình cho những điều này?
HalosGhost

Chỉnh sửa xin lỗi các bạn.
Avinash Raj

Các chỉnh sửa của bạn chưa thực sự làm rõ ví dụ của bạn. Xin vui lòng xem bình luận cuối cùng của tôi .
HalosGhost

xóa tất cả dấu phẩy bên trong dấu ngoặc kép và cả dấu ngoặc kép chỉ khi dấu ngoặc kép chứa số.
Avinash Raj

Câu trả lời:


7

Điều này (được điều chỉnh từ đây ) sẽ làm những gì bạn cần mặc dù Perl one của @ rici đơn giản hơn nhiều:

$ sed -r ':a;s/(("[0-9,]*",?)*"[0-9,]*),/\1/;ta; s/""/","/g; 
          s/"([0-9]*)",?/\1,/g ' file
56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454,
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"

Giải trình

  • :a: xác định nhãn gọi là a.
  • s/(("[0-9,]*",?)*"[0-9,]*),/\1/ : Cái này cần được chia nhỏ
    • Trước hết, sử dụng cấu trúc này : (foo(bar)), \1sẽ foobar\2sẽ bar.
    • "[0-9,]*",?: khớp 0 hoặc nhiều hơn 0-9hoặc ,, theo sau là 0 hoặc 1 ,.
    • ("[0-9,]*",?)* : khớp 0 hoặc nhiều hơn ở trên.
    • "[0-9,]*: khớp 0 hoặc nhiều hơn 0-9hoặc ,đến ngay sau một"
  • ta;: quay lại nhãn avà chạy lại nếu thay thế thành công.
  • s/""/","/g;: xử lý hậu kỳ. Thay thế ""bằng ",".
  • s/"([0-9]*)",?/\1,/g : xóa tất cả các trích dẫn xung quanh số.

Điều này có thể dễ hiểu hơn với một ví dụ khác:

$ echo '"1,2,3,4"' | sed -nr ':a;s/(("[0-9,]*",?)*"[0-9,]*),/\1/;p;ta;'
"1,2,34"
"1,234"
"1234"
"1234"

Vì vậy, trong khi bạn có thể tìm thấy một số ngay sau một trích dẫn và theo sau là dấu phẩy và một số khác, hãy nối hai số đó lại với nhau và lặp lại quy trình cho đến khi không còn có thể.

Tại thời điểm này, tôi tin rằng thật hữu ích khi đề cập đến một trích dẫn info sedxuất hiện trong phần mô tả các chức năng nâng cao như nhãn được sử dụng ở trên (cảm ơn vì đã tìm thấy nếu @Braiam):

Trong hầu hết các trường hợp, việc sử dụng các lệnh này chỉ ra rằng bạn có thể tốt hơn là lập trình trong một cái gì đó như 'awk' hoặc Perl.


10

Nếu perl là OK, đây là một cách ngắn (và có thể nhanh, nếu không nhất thiết phải đơn giản :)):

perl -pe 's:"(\d[\d,]+)":$1=~y/,//dr:eg' file

Các elá cờ để các s:::nhà điều hành (mà chỉ là một cách khác để viết s///) gây ra thay thế được đối xử như một thành ngữ được đánh giá mỗi lần. Biểu thức đó lấy bản $1chụp từ regex (đã thiếu dấu ngoặc kép) và dịch ( y///, cũng có thể được viết là tr///) nó bằng cách xóa ( /d) tất cả các dấu phẩy. Các rlá cờ để ylà cần thiết để có được giá trị là chuỗi dịch, thay vì số lượng các bản dịch.

Đối với những người bằng cách nào đó cảm thấy buồn bã bởi perl, đây là con trăn tương đương. Python thực sự không phải là một công cụ một lớp vỏ, nhưng đôi khi nó có thể được đưa vào hợp tác. Dòng sau đây có thể được viết dưới dạng một dòng (không giống như forcác vòng lặp, không thể), nhưng cuộn ngang làm cho nó (thậm chí nhiều hơn) không thể đọc được:

python -c '
import re;
import sys;
r=re.compile("\"(\d+(,\d+)*)\"");
all(not sys.stdout.write(r.sub(lambda m:m.group(1).replace(",",""),l))
    for l in sys.stdin)
' < file

@rici: Tốt lắm! Và sử dụng y///thay vì tr///tiết kiệm cho chúng tôi thêm một nhân vật.
cuonglm

6

Đối với dữ liệu CSV, tôi sẽ sử dụng ngôn ngữ với trình phân tích cú pháp CSV thực. Ví dụ với Ruby:

ruby -rcsv -pe '
  row = CSV::parse_line($_).map {|e| e.delete!(",") if e =~ /^[\d,]+$/; e} 
  $_  = CSV::generate_line(row)
' <<END
56,72,"12,34,54",x,y,"foo,a,b,bar"
56,92,"12,34",x,y,"foo,a,b,bar"
56,72,"12,34,54,78,76,54,67",x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar","12,34,54"
56,72,x,y,"foo,a,b,bar","12,34,54","45,57,84,92","bar,foo"
END
56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"

0

Blockquote

Xin chào Đây là mã Python để Thay thế dấu phẩy bằng dấu ngoặc kép, dấu phẩy được thay thế bằng ký tự pipe (|)

Mã Python này là để thay thế dấu phẩy được đặt trong dấu ngoặc kép

ví dụ: x, y, z, 1,2, "r, e, t, y", h, 8,5,6

nếu thay thế bằng Ống x, y, z, 1,2, "r | e | t | y", h, 8,5,6

nếu thay thế bằng null x, y, z, 1,2, "rety", h, 8,5,6

writingFile = open('FileToWrite', 'w')
with open('FileToRead') as f:

    while True:

        c = f.read(1)
        if not c:
            print ("End of file")
            break
        print ("Read a character:", c)


        if c=='"':
            writingFile.write(c) 
            c = f.read(1)
            while c != '"':
                if c== ',':
                    c= '|'
                writingFile.write(c)
                c = f.read(1)


        writingFile.write(c)


writingFile.close()

ít lời giải thích cần thiết.
Mongrel

Mã trăn này được sử dụng để thay thế mọi thứ trong dấu ngoặc kép
Vijay Kumar Akarapu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.