Trích xuất một phần của một dòng từ một tệp có sed


18

Tôi muốn đọc một phần của một dòng từ một tập tin. Ví dụ:

POP3_SERVER_NAME = localhost

Tôi chỉ muốn trở về localhost, sử dụng sed.

Văn bản này là trên dòng thứ ba. Tôi làm điều này để trích xuất dòng:

sed -n '3p' installation.sh

Làm thế nào để tôi chỉ trích xuất localhostmột phần?

Câu trả lời:


26

awk có thể là một công cụ tốt hơn ở đây.

$ cat test.dat
LINE 1
LINE 2
POP3_SERVER_NAME = localhost

Tìm kiếm các dòng có chứa "POP3_SERVER_NAME"; in trường cuối cùng. Điều này không phụ thuộc vào POP3_SERVER_NAME luôn nằm trên dòng 3, đây có lẽ là một điều tốt.

$ awk '/POP3_SERVER_NAME/{print $NF}' test.dat
localhost

Tùy thuộc vào ứng dụng của bạn, bạn có thể cần phải thực hiện biểu thức chính quy nghiêm ngặt hơn. Ví dụ: bạn có thể chỉ muốn khớp dòng đó bắt đầu bằng POP3_SERVER_NAME.

$ awk '/^POP3_SERVER_NAME/{print $NF}' test.dat
localhost

Sử dụng sed là một chút ít trực quan. (Cảm ơn, tôi biết về sự trớ trêu.) Địa chỉ dòng có chứa POP3_SERVER_NAME ở bất cứ đâu. Thay thế một chuỗi trống cho tất cả văn bản từ đầu dòng đến không gian tùy chọn theo sau "=". Sau đó in.

sed -n -e '/POP3_SERVER_NAME/ s/.*\= *//p' test.dat

2
Các awklệnh là tốt đẹp - nhưng chỉ khi bạn đã có không gian xung quanh =. Nó sẽ không làm việc cho POP3_SERVER_NAME=localhost.
Marcel Stor

2
@Marcel, Bạn có thể thay đổi dấu phân cách được sử dụng awktừ khoảng trắng sang thứ khác bằng cách sử dụng -F. Ví dụ: -F "="sẽ sử dụng =như một dấu phân cách trong trường hợp bạn đề cập.
mattpr

7

Thay thế plệnh bằng một thay thế loại bỏ phần không mong muốn của dòng.

sed -n '3 s/^[^=]*= *//p' installation.sh

Bạn có thể muốn khớp dòng theo từ khóa hơn là theo vị trí.

sed -n 's/^ *POP3_SERVER_NAME *= *//p' installation.sh

5
echo "POP3_SERVER_NAME = localhost" | sed 's/.*= //'
localhost

Hoặc nếu bạn có nội dung trong một tệp:

sed 's/.*= //' somefile.txt
localhost

ok, nhưng tôi đã đọc trong tập tin của mình như thế này: sed -n '3p' install.sh
Mercer

2
@Mercer - xem các cập nhật tôi đã thêm vào câu trả lời.
slm

@Adam Siemion - cảm ơn bạn, nhưng làm thế nào để chỉ ra số dòng?
Mercer

5

Có vẻ như bạn đã có một tập tin cấu hình. Những gì bạn có thể làm tương tự như những gì Adam Siemeon / slm gợi ý:

sed -nr 's/[^=]+=\s*(.+)$/\1/p' filename

nơi [^=]không bao gồm tất cả '=' nhân vật, +cho biết một hoặc nhiều cùng một loại nhân vật, điều này tiếp theo là một thực tế =, \sbất kỳ khoảng trắng (bao gồm cả các tab \tvà dây chuyền mới \n, \r\nvà không gian đơn giản '', trong khi *phương tiện bằng không hoặc nhiều cùng loại , dấu ngoặc đơn bắt những gì bên trong để đặt các chuỗi ký tự trùng khớp vào các vị trí thay thế \ 1, \ 2, ..., \ n, $có nghĩa là kết thúc một dòng. Điều này tuân theo mẫu thay thế điển hình của : s/.../.../modifiers. Tùy chọn dòng lệnh -rlà viết tắt của cú pháp regex mở rộng (như một vấn đề thuận tiện) và -ncó nghĩa là đầu ra không có gì cho đến khi hoặc trừ khi được yêu cầu một cách rõ ràng. Công cụ psửa đổi in ra kết quả.

Bạn có thể thực hiện tìm kiếm toàn cầu với công cụ gsửa đổi như:

sed -nr 's/[^=]+=\s*(.+)$/\1 /pg' filename  # note the space after \1

để bạn có được một chuỗi phân cách bằng ' '(có thể là \n, \thoặc những gì có bạn) mà bạn có thể xử lý một cách dễ dàng.

Cả hai đều hợp lệ với điều kiện các giá trị của bạn đứng trước ký tự phương trình kéo dài đến cuối dòng và không được theo sau bởi các nhận xét hoặc các ký tự khác có ngữ nghĩa lệch khỏi một "giá trị" đơn giản.


Biên tập:

Tôi không thể bình luận ở đây về bài viết của người khác. Để chỉ ra dòng chỉ cần vượt qua số dòng, trong trường hợp của bạn 3, trước shoặc trước trích dẫn char (giống như trong vim).

sed -nr '3s/[^=]+=\s*(.+)$/\1/p' filename

Xin hãy xem info sed. Ví dụ, 3.2 và 4.7 được bạn đặc biệt quan tâm.


4

Bạn có thể sử dụng lệnh cắt, đặt dấu phân cách thành '=' và sau đó in trường thứ hai như thế này:

cut -d'=' -f2

3

Nhiều cách để làm điều đó, xem xét tệp của bạn được gọi là foobar:

Chỉ định mẫu để tìm kiếm:

PAT=POP3_SERVER_NAME

Trích xuất bằng sed

sed -n "/$PAT/p" foobar | sed "s/$PAT = //"

Hoặc sử dụng sedcut

sed -n "/$PAT/p" foobar | cut -d' ' -f3

2

Vẻ đẹp của Linux / Unix là thường có nhiều hơn một cách để hoàn thành một cái gì đó. Trong trường hợp của op, có ít nhất bốn cách khác nhau để trích xuất tên máy chủ POP từ tệp:

  1. grep POP3_SERVER_NAME installation.sh | cut -d'=' -f2
  2. grep POP3_SERVER_NAME installation.sh | awk '{print $3}'
  3. grep POP3_SERVER_NAME installation.sh | sed 's/.*= //'
  4. sed -n 's/^.*POP3_SERVER_NAME = //p' installation.sh
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.