Tham gia nhiều lệnh sed trong một tập lệnh để xử lý tệp CSV


34

Có tệp CSV như thế này:

HEADER
"first, column"|"second "some random quotes" column"|"third ol' column"
FOOTER

và tìm kiếm kết quả như:

HEADER
first, column|second "some random quotes" column|third ol' column

nói cách khác, loại bỏ "BÓNG ĐÁ", trích dẫn ở đầu, cuối và xung quanh |.

Cho đến nay mã này hoạt động:

sed '/FOOTER/d' csv > csv1 | #remove FOOTER
sed 's/^\"//' csv1 > csv2 | #remove quote at the beginning
sed 's/\"$//' csv2 > csv3 | #remove quote at the end
sed 's/\"|\"/|/g' csv3 > csv4 #remove quotes around pipe

Như bạn thấy vấn đề là nó tạo thêm 4 tệp.

Đây là một giải pháp khác, có một mục tiêu là không tạo thêm tệp và thực hiện điều tương tự trong một tập lệnh. Nó không hoạt động rất tốt.

#!/bin/ksh

sed '/begin/, /end/ { 
        /FOOTER/d
        s/^\"//
        s/\"$//
        s/\"|\"/|/g 
}' csv > csv4

1
Vì bạn đang có dấu ngoặc kép, bạn có thể có dòng mới trong các lĩnh vực. bạn sedsẽ không làm việc với điều đó, chỉ với csv đơn giản hóa. Sử dụng ngôn ngữ lập trình với thư viện có thể xử lý các tệp CSV thực (Python / Perl / Ruby).
Anthon

Câu trả lời:


44

Trước hết, như Michael đã chỉ ra, bạn chỉ có thể kết hợp tất cả những điều này thành một lệnh duy nhất:

sed '/^FOOTER/d; s/^\"//; s/\"$//; s/\"|\"/|/g' csv > csv1

Tôi nghĩ rằng một số sedtriển khai không thể đối phó với điều đó và có thể cần:

  sed -e '/^FOOTER/d' -e 's/^\"//' -e 's/\"$//' -e 's/\"|\"/|/g' csv > csv1

Điều đó nói rằng, có vẻ như các trường của bạn được xác định bởi |và bạn chỉ muốn xóa "xung quanh toàn bộ trường, để lại những trường nằm trong trường. Trong trường hợp đó, bạn có thể làm:

$ sed '/FOOTER/d; s/\(^\||\)"/\1/g; s/"\($\||\)/\1/g' csv 
HEADER
first, column|second "some random quotes" column|third ol' column

Hoặc, với GNU sed:

sed -r '/FOOTER/d; s/(^|\|)"/\1/g; s/"($|\|)/\1/g' csv 

Bạn cũng có thể sử dụng Perl:

$ perl -F"|" -lane 'next if /FOOTER/; s/^"|"$// for @F; print @F' csv 
HEADER
first, column|second some random quotes column|third ol' column

13

Điều này cũng sẽ làm việc:

sed 's / ^ "//; s /" | "/ | / g; s /" "$ /" /'

Thí dụ:

$ echo '"this"|" and "ths""|" and "|" this 2"|" also "this", "thi", "and th""' | 
sed 's/^"//; s/"|"/|/g; s/""$/"/'
this| and "ths"| and | this 2| also "this", "thi", "and th"

phiên bản đẹp

sed '
s/^"//
s/"|"/|/g
s/""$/"/
$d
'

1
Điều này không đối phó với chân trang.
terdon

3
Nhưng điều đó sẽ loại bỏ dòng cuối cùng cho dù nội dung của nó là gì. Nếu không có FOOTER, nó sẽ xóa dữ liệu mong muốn.
terdon
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.