Tìm kiếm một cái gì đó như thế này? Có ý kiến gì không?
cmd | prepend "[ERRORS] "
[ERROR] line1 text
[ERROR] line2 text
[ERROR] line3 text
... etc
Tìm kiếm một cái gì đó như thế này? Có ý kiến gì không?
cmd | prepend "[ERRORS] "
[ERROR] line1 text
[ERROR] line2 text
[ERROR] line3 text
... etc
Câu trả lời:
cmd | while read line; do echo "[ERROR] $line"; done
có lợi thế là chỉ sử dụng các nội dung bash để tạo ra / phá hủy ít quy trình hơn nên nó sẽ nhanh hơn một chút so với awk hoặc sed.
@tzrik chỉ ra rằng nó cũng có thể tạo ra một hàm bash đẹp. Xác định nó như sau:
function prepend() { while read line; do echo "${1}${line}"; done; }
sẽ cho phép nó được sử dụng như:
cmd | prepend "[ERROR] "
sed
) hoặc thậm chí tách chuỗi ( awk
).)
function prepend() { while read line; do echo "${1}${line}"; done; }
Thử đi:
cmd | awk '{print "[ERROR] " $0}'
Chúc mừng
awk -vT="[ERROR] " '{ print T $0 }'
hoặcawk -vT="[ERROR]" '{ print T " " $0 }'
T="[ERROR] " awk '{ print ENVIRON["T"] $0 }'
hoặcT="[ERROR]" awk '{ print ENVIRON["T"] " " $0 }'
cmd | awk '{print "['$V]' " $0}'
- điều này nên được đánh giá một lần khi bắt đầu, do đó không có chi phí hiệu năng.
Với tất cả tín dụng dành cho @grawity, tôi đang gửi bình luận của anh ấy như một câu trả lời, vì đây có vẻ là câu trả lời tốt nhất ở đây cho tôi.
sed 's/^/[ERROR] /' cmd
awk
lớp lót là đủ tốt, nhưng tôi nghĩ rằng nhiều người quen thuộc sed
hơn awk
. Kịch bản bash tốt cho những gì nó làm, nhưng có vẻ như nó đang trả lời một câu hỏi không được hỏi.
sed X cmd
không đọc cmd
và không thực hiện nó. Hoặc cmd | sed 's/^/[ERROR] /'
hoặc sed 's/^/[ERROR] /' <(cmd)
hoặc cmd > >(sed 's/^/[ERROR] /')
. Nhưng hãy cẩn thận sau. Thậm chí điều này cho phép bạn truy cập giá trị trả về của cmd
các sed
lần chạy trong nền, vì vậy có khả năng bạn sẽ thấy đầu ra sau khi cmd kết thúc. Tốt để đăng nhập vào một tập tin, mặc dù. Và lưu ý rằng awk
có lẽ là nhanh hơn sed
.
alias lpad="sed 's/^/ /'"
. thay vì LRI tôi chèn 4 khoảng trắng hàng đầu. Bây giờ, đối với trò ảo thuật: ls | lpad | pbcopy
sẽ bổ sung đầu ra ls với 4 khoảng trắng đánh dấu nó là Markdown cho mã , nghĩa là bạn dán bảng tạm ( pbcopy lấy nó, trên mac) trực tiếp vào StackOverflow hoặc bất kỳ bối cảnh đánh dấu nào khác. Không thể alias
các awk câu trả lời (ngày 1 thử) vì vậy đây là một chiến thắng. Các giải pháp trong khi đọc cũng có khả năng bí danh, nhưng tôi thấy sed này biểu cảm hơn.
Tôi đã tạo một kho lưu trữ GitHub để thực hiện một số bài kiểm tra tốc độ.
Kết quả là:
awk
là nhanh nhất. sed
chậm hơn một chút và perl
không chậm hơn nhiều sed
. Rõ ràng, tất cả những thứ đó là ngôn ngữ được tối ưu hóa cao để xử lý văn bản.ksh
lệnh được biên dịch ( shcomp
) có thể tiết kiệm nhiều thời gian xử lý hơn. Ngược lại, bash
là chết chậm so với ksh
các kịch bản được biên dịch .awk
dường như không đáng nỗ lực.Ngược lại python
là chết chậm, nhưng tôi đã không kiểm tra một trường hợp được biên dịch, bởi vì đó thường không phải là những gì bạn sẽ làm trong trường hợp kịch bản như vậy.
Các biến thể sau đây được thử nghiệm:
while read line; do echo "[TEST] $line"; done
while read -r line; do echo "[TEST] $line"; done
while read -r line; do echo "[TEST]" $line; done
while read -r line; do echo "[TEST]" "$line"; done
sed 's/^/[TEST] /'
awk '{ print "[TEST] " $0 }'
awk -vT="[TEST] " '{ print T $0 }'
awk -vT="[TEST]" '{ print T " " $0 }'
awk -vT="[TEST]" 'BEGIN { T=T " "; } { print T $0 }'
T="[TEST] " awk '{ print ENVIRON["T"] $0 }'
T="[TEST]" awk '{ print ENVIRON["T"] " " $0 }'
T="[TEST]" awk 'BEGIN { T=ENVIRON["T"] " " } { print T $0 }'
perl -ne 'print "[TEST] $_"'
Hai biến thể nhị phân của một trong những công cụ của tôi (tuy nhiên nó không được tối ưu hóa cho tốc độ):
./unbuffered.dynamic -cp'[TEST] ' -q ''
./unbuffered.static -cp'[TEST] ' -q ''
Bộ đệm Python:
python -uSc 'import sys
for line in sys.stdin: print "[TEST]",line,'
Và Python không có bộ đệm:
python -uSc 'import sys
while 1:
line = sys.stdin.readline()
if not line: break
print "[TEST]",line,'
awk -v T="[TEST %Y%m%d-%H%M%S] " '{ print strftime(T) $0 }'
để xuất dấu thời gian
Tôi muốn một giải pháp xử lý thiết bị xuất chuẩn và thiết bị xuất chuẩn, vì vậy tôi đã viết prepend.sh
và đưa nó vào đường dẫn của mình:
#!/bin/bash
prepend_lines(){
local prepended=$1
while read line; do
echo "$prepended" "$line"
done
}
tag=$1
shift
"$@" > >(prepend_lines "$tag") 2> >(prepend_lines "$tag" 1>&2)
Bây giờ tôi chỉ có thể chạy prepend.sh "[ERROR]" cmd ...
, để thêm "[ERROR]" vào đầu ra của cmd
, và vẫn có stderr và stdout riêng biệt.
>(
khung con mà tôi không thể giải quyết được. Có vẻ như tập lệnh đã hoàn tất, và đầu ra đang đến thiết bị đầu cuối sau khi lời nhắc đã trở lại, hơi lộn xộn. Cuối cùng tôi đã đưa ra câu trả lời ở đây stackoverflow.com/a/25948606/409638