tạo đầu ra grep mà không theo dõi dòng mới


8

Vui lòng xem xét đoạn trích này:

X=$(grep -m1 'some-pattern' some-file | sed -n 's/.* //p')

Tôi muốn đặt từ cuối cùng vào một biến nếu một số điều kiện mẫu được khớp với các dòng trong tệp văn bản tùy ý

Vấn đề của tôi là biến đó Xcó CR hoặc LF hoặc CRLF ở cuối, tùy thuộc vào tệp nguồn mà tôi muốn loại bỏ, vì nó can thiệp vào hoạt động sau này tôi dự định thực hiện.
Tôi thậm chí đã thử một cái gì đó như:

X=$(grep -m1 'some-pattern' some-file | sed -n 's/.* \([A-Za-z]\+\)/\1/p')

do đó hy vọng sedđầu ra bị hạn chế [A-Za-z]+nhưng vẫn còn các byte phiền toái này bên trong biến X.

Làm thế nào tôi có thể thoát khỏi nó, mà không sử dụng quá nhiều mã như see gì byte là lúc kết thúc với xxdsau đó cutnó và tương tự như các biến chứng?

Câu trả lời:


4

Có vẻ như awkđó sẽ là lựa chọn tốt hơn cho nhu cầu của bạn, vì những vấn đề này không tồn tại do thực tế là nó có thể sử dụng các trường và bản ghi:

x=$(awk '/some-pattern/ { sub(/\r$/, "") ; printf("%s", $NF) ; exit }' some-file)

Sự thay thế sẽ tránh được vấn đề của bạn với các kết thúc dòng CRLF.

sub(/\r$/, "")loại bỏ CR dấu, nếu nó tồn tại. Như được awkcoi \nlà dấu tách (dòng) bản ghi, bạn không cần phải loại bỏ nó, vì nó không nằm trong dữ liệu được xem xét.

printf("%s", $NF)in trường cuối cùng ( $NF) không có dòng mới ( printvà một số awkchức năng khác nối thêm dòng mới theo mặc định).

exitxảy ra sau hai hành động đầu tiên - điều này tương đương với m1trong grepdòng lệnh của bạn . Điều này đảm bảo awkthoát ra sau khi thực hiện hai lệnh trước - và vì các lệnh này được ban hành khi khớp và awk đánh giá dữ liệu theo cách thức của FIFO, nên điều này sẽ chỉ in trận đấu đầu tiên.


Cảm ơn, nó trông thanh lịch nhưng tiếc là CRLF vẫn ở bên trongX
zetah

:) Bây giờ nó trông không còn thanh lịch nữa và nó vẫn không còn tốt nữa
zetah

@zetah - Sẽ không có CR, nhưng sẽ có một LF. Tôi đã có một thời gian khó hiểu những gì bạn muốn từ câu hỏi, hy vọng chỉnh sửa của tôi làm những gì bạn muốn.
Chris Down

OK, lần này nó hoạt động tốt - xuất từ ​​cuối cùng trong một dòng nếu dòng đó thỏa mãn một số điều kiện mẫu - không biết, có thể nó rõ ràng với tôi vì tôi gặp vấn đề này, và sau đó khó giải thích là người nói tiếng Anh không phải là người bản ngữ . Dù sao đi nữa, tôi sẽ đợi thêm một chút nếu ai đó giải quyết vấn đề này bằng grep/sedgiải pháp thay thế awk(mà tôi không hiểu), và nếu không tôi sẽ sử dụng nó. Cảm ơn
zetah

@zetah - Tôi sẽ thêm một lời giải thích để bạn có thể hiểu nó tốt hơn, một giây.
Chris Down

7

Các ``hoặc $()sẽ loại bỏ các newline từ cuối cùng, nhưng để làm được điều này programatically, sử dụng tr.

grep -m1 'some-pattern' some-file | sed -n 's/.* //p' | tr -d '\012\015'

Điều này sẽ loại bỏ trả lại vận chuyển và / hoặc dòng mới từ chuỗi.

Điều có thể là vấn đề là làm thế nào bạn xuất kết quả. Ví dụ, theo mặc định, echothêm một dòng mới. Bạn có thể muốn sử dụng echo -nhoặc printf.


Điều này cũng sẽ loại bỏ trả lại vận chuyển có thể xảy ra trong toàn bộ chuỗi, có thể không mong muốn.
Chris Down

Có, trong khi có thể có một lợi nhuận vận chuyển được nhúng trong một dòng duy nhất, nó là cực kỳ hiếm. Các -m1sẽ đảm bảo rằng chỉ có một đầu ra đường, mà trong tất cả các khả năng, sẽ có sự trở lại vận chuyển ở cuối.
Arcege

à tr... thật thú vị, hoạt động cả trên các tập tin LF và CRLF. Tôi sẽ suy nghĩ \010\013vì một số lý do, và cũng \f\rhoạt động chính xác. Về kết quả: Tôi thực sự không đặt đầu ra trong biến mà là biến được đặt $()trong mẫu cho grepkhớp - some pipe | grep -o " $(...) ". Cảm ơn các ý kiến
zetah

3

Tôi thích cách này

grep -m1 'some-pattern' some-file | sed -n 's/.* //p' | tr -d '\n'

2

Điều này làm việc cho tôi:

grep -m1 'some-pattern' some-file | sed -n 's/.* //p' | tr -d "\n" | tr -d "\r"

0

Tại sao không chỉ đơn giản là để sedlàm [\r\f]sạch:

# using Bash's $'string' idiom (that decodes ANSI C escape sequences)
# cf. http://wiki.bash-hackers.org/syntax/quoting#ansi_c_like_strings
- X="$(grep -m1 'some-pattern' some-file | sed -n 's/.* //p')"
+ X="$(grep -m1 'some-pattern' some-file | sed -n -e $'s/[\r\f]*$//' -e 's/.* //p')"

Cách tiếp cận thứ hai của bạn thiếu một biểu thức chính thức cuối cùng để bắt CR \r.

# sample code to remove trailing \r with sed
# cf. http://en.wikipedia.org/wiki/Regular_expression#POSIX_character_classes
printf 'a b c\r' | sed -n 's/^.* \([[:alpha:]]\{1,\}\)/\1/p' | od -c
printf 'a b c\r' | sed -n 's/^.* \([[:alpha:]]\{1,\}\)[[:space:]]*/\1/p' | od -c

# keeps trailing space after c
printf 'a b c \r' | sed -n 's/^.* \([[:alpha:] ]\{1,\}\)[[:space:]]*/\1/p' | od -b

0

Phiên bản bình thường của grep (bao gồm grep -P) luôn xuất ra một nguồn cấp dữ liệu phù hợp với kết quả khớp của nó, vì vậy nếu bạn chỉ có một kết quả (hoặc bạn chỉ muốn loại bỏ nguồn cấp dữ liệu được thêm vào cuối cùng), thì chỉ cần loại bỏ ký tự cuối cùng của đầu ra, mà bạn có thể làm bằng cách dẫn nó qua head -c-1.

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.