2013-05-21 29 views
24

Tôi có một tập tin chứa các dòng sau:Làm thế nào để sử dụng sed để trích xuất chuỗi

<parameter name="PortMappingEnabled" access="readWrite" type="xsd:boolean"></parameter> 
    <parameter name="PortMappingLeaseDuration" access="readWrite" activeNotify="canDeny" type="xsd:unsignedInt"></parameter> 
    <parameter name="RemoteHost" access="readWrite"></parameter> 
    <parameter name="ExternalPort" access="readWrite" type="xsd:unsignedInt"></parameter> 
    <parameter name="ExternalPortEndRange" access="readWrite" type="xsd:unsignedInt"></parameter> 
    <parameter name="InternalPort" access="readWrite" type="xsd:unsignedInt"></parameter> 
    <parameter name="PortMappingProtocol" access="readWrite"></parameter> 
    <parameter name="InternalClient" access="readWrite"></parameter> 
    <parameter name="PortMappingDescription" access="readWrite"></parameter> 

Tôi muốn thực hiện lệnh trong hồ sơ này để trích xuất chỉ tên tham số như được hiển thị trong các kết quả sau:

$sedcommand file.txt 
PortMappingEnabled 
PortMappingLeaseDuration 
RemoteHost 
ExternalPort 
ExternalPortEndRange 
InternalPort 
PortMappingProtocol 
InternalClient 
PortMappingDescription 

Lệnh này có thể là gì?

+1

Lưu ý rằng bạn sẽ buồn khi XML đó đến với bạn trên nhiều dòng, hoặc nếu thứ tự của các đối số thay đổi. Nếu đó là một khả năng, bạn sẽ muốn xem xét sử dụng một trình phân tích cú pháp XML thích hợp. –

+0

Hm, tiêu chuẩn kép với các câu hỏi có thể được trả lời trong 10 giây so với những câu hỏi yêu cầu nhiều thời gian hơn? Bài đăng hỏi bạn đã thử ở đâu? Oh wait ... – rliu

Trả lời

24

Bạn muốn awk.

Đây sẽ là một hack nhanh chóng và dơ bẩn:

awk -F "\"" '{print $2}' /tmp/file.txt

PortMappingEnabled 
PortMappingLeaseDuration 
RemoteHost 
ExternalPort 
ExternalPortEndRange 
InternalPort 
PortMappingProtocol 
InternalClient 
PortMappingDescription 
+0

'cut' sẽ thực hiện công việc nhanh hơn :-) –

36

sed 's/[^"]*"\([^"]*\).*/\1/'

hiện công việc.

+6

+1 Đẹp, đơn giản và thanh lịch !!! Yêu nó!!! – Barranka

+32

Đó không phải là đơn giản cũng không thanh lịch. Chỉ là khó hiểu. – Stefan

+11

@Stefan, với mắt chưa được đào tạo có lẽ. Nhưng dành thời gian với RegEx và như jazz hay Picasso, bạn sẽ đánh giá cao vẻ đẹp đơn giản. – SaxDaddy

64

grep được sinh ra để trích xuất điều:

grep -Po 'name="\K[^"]*' 

kiểm tra với dữ liệu của bạn:

kent$ echo '<parameter name="PortMappingEnabled" access="readWrite" type="xsd:boolean"></parameter> 
    <parameter name="PortMappingLeaseDuration" access="readWrite" activeNotify="canDeny" type="xsd:unsignedInt"></parameter> 
    <parameter name="RemoteHost" access="readWrite"></parameter> 
    <parameter name="ExternalPort" access="readWrite" type="xsd:unsignedInt"></parameter> 
    <parameter name="ExternalPortEndRange" access="readWrite" type="xsd:unsignedInt"></parameter> 
    <parameter name="InternalPort" access="readWrite" type="xsd:unsignedInt"></parameter> 
    <parameter name="PortMappingProtocol" access="readWrite"></parameter> 
    <parameter name="InternalClient" access="readWrite"></parameter> 
    <parameter name="PortMappingDescription" access="readWrite"></parameter> 
'|grep -Po 'name="\K[^"]*' 
PortMappingEnabled 
PortMappingLeaseDuration 
RemoteHost 
ExternalPort 
ExternalPortEndRange 
InternalPort 
PortMappingProtocol 
InternalClient 
PortMappingDescription 
+4

Chỉ cần FYI, từ trang web grep về '-P':" Đây là thử nghiệm cao và ** grep -P ** có thể cảnh báo về các tính năng chưa được thực hiện. " –

+0

Không phải tất cả các bản phân phối * nix đều hỗ trợ 'grep -o'. Một ví dụ tôi biết là AIX –

+0

@FukuzawaYukio Tôi nghĩ rằng grep được vận chuyển bởi linux ubuntu nên hỗ trợ nó phải không? mặc dù tôi không phải là người dùng ubuntu. Câu hỏi được gắn thẻ với Linux & ubuntu, không phải Unix hoặc Aix. Nhưng bạn bình luận là chính xác. – Kent

12

Bạn không nên phân tích cú pháp XML sử dụng các công cụ như sed, awk hoặc. Nó dễ bị lỗi.

Nếu thay đổi đầu vào và trước thông số tên, bạn sẽ nhận được ký tự dòng mới thay vì khoảng trống, nó sẽ không thành công vào một ngày nào đó tạo ra kết quả không mong muốn.

Nếu bạn thực sự chắc chắn, đầu vào của bạn sẽ luôn được định dạng theo cách này, bạn có thể sử dụng cut. Đó là nhanh hơn so với sedawk:

cut -d'"' -f2 < input.txt 

Nó sẽ là tốt hơn để lần đầu tiên phân tích nó, và giải nén chỉ tên tham số thuộc tính:

xpath -q -e //@name input.txt | cut -d'"' -f2 

Để tìm hiểu thêm về xpath, xem hướng dẫn này: http://www.w3schools.com/xpath/