Giả sử tôi có một số đầu ra từ một lệnh (chẳng hạn như ls -1):
a
b
c
d
e
...
Tôi muốn áp dụng một lệnh (nói echo) cho từng người, lần lượt. Ví dụ
echo a
echo b
echo c
echo d
echo e
...
Cách dễ nhất để làm điều đó trong bash là gì?
Giả sử tôi có một số đầu ra từ một lệnh (chẳng hạn như ls -1):
a
b
c
d
e
...
Tôi muốn áp dụng một lệnh (nói echo) cho từng người, lần lượt. Ví dụ
echo a
echo b
echo c
echo d
echo e
...
Cách dễ nhất để làm điều đó trong bash là gì?
Câu trả lời:
Nó có lẽ dễ sử dụng nhất xargs. Trong trường hợp của bạn:
ls -1 | xargs -L1 echo
Các -Lcờ đảm bảo đầu vào được đọc đúng cách. Từ trang người đàn ông của xargs:
-L number
Call utility for every number non-empty lines read.
A line ending with a space continues to the next non-empty line. [...]
lstự động làm -1trong một đường ống.
ls | xargs -L2 echovà ls -1 | xargs -L2 echođưa ra hai kết quả đầu ra khác nhau. Các cựu là tất cả trên một dòng.
xargschỉ có thể chạy các tệp thực thi chứ không phải các hàm shell hoặc các lệnh dựng sẵn. Đối với trước đây, giải pháp tốt nhất có lẽ là một readtrong một vòng lặp.
-L1là cho.
Bạn có thể sử dụng thao tác trả trước cơ bản trên mỗi dòng:
ls -1 | while read line ; do echo $line ; done
Hoặc bạn có thể chuyển đầu ra sang sed cho các hoạt động phức tạp hơn:
ls -1 | sed 's/^\(.*\)$/echo \1/'
sh: cho: not found a sh: cho: not foundCó vẻ như nó lấy etiếng vang là lệnh sed hay gì đó.
whilevòng lặp. cmd1 | while read line; do cmd2 $line; done. Hoặc while read line; do cmd2 $line; done < <(cmd1)không tạo ra một subshell. Đây là phiên bản đơn giản hóa của sedlệnh của bạn :sed 's/.*/echo &/'
"$line"trong vòng lặp while, để tránh chia tách từ.
read -r lineđể tránh readgây rối với các ký tự thoát. Ví dụ echo '"a \"nested\" quote"' | while read line; do echo "$line"; donecho "a "nested" quote", mà đã mất thoát. Nếu chúng ta làm, echo '"a \"nested\" quote"' | while read -r line; do echo "$line"; donechúng ta nhận được "a \"nested\" quote"như mong đợi. Xem wiki.bash-hackers.org/commands/builtin/read
Bạn có thể sử dụng vòng lặp for :
cho tệp trong *; làm tiếng vang "tập tin $" làm xong
Lưu ý rằng nếu lệnh trong câu hỏi chấp nhận nhiều đối số, thì việc sử dụng xargs hầu như luôn hiệu quả hơn vì nó chỉ phải sinh ra tiện ích trong câu hỏi một lần thay vì nhiều lần.
printf '%s\0' * | xargs -0 ...- nếu không, nó khá không an toàn với tên tệp có khoảng trắng, dấu ngoặc kép, v.v.
Bạn thực sự có thể sử dụng sed để làm điều đó, với điều kiện đó là GNU sed.
... | sed 's/match/command \0/e'
Làm thế nào nó hoạt động:
cat /logs/lfa/Modified.trace.log.20150904.pw | sed -r 's/^(.*)(\|006\|00032\|)(.*)$/echo "\1\2\3 - ID `shuf -i 999-14999 -n 1`"/e'
for s in `cmd`; do echo $s; done
Nếu cmd có đầu ra lớn:
cmd | xargs -L1 echo
cmdcó khoảng trắng trong đầu ra của nó, cái đầu tiên sẽ thất bại.
xargs thất bại với dấu gạch chéo ngược, dấu ngoặc kép. Nó cần phải là một cái gì đó như
ls -1 |tr \\n \\0 |xargs -0 -iTHIS echo "THIS is a file."
tùy chọn xargs -0:
-0, --null Input items are terminated by a null character instead of by whitespace, and the quotes and backslash are not special (every character is taken literally). Disables the end of file string, which is treated like any other argument. Useful when input items might contain white space, quote marks, or backslashes. The GNU find -print0 option produces input suitable for this mode.
ls -1chấm dứt các mục với các ký tự dòng mới, do đó trchuyển chúng thành các ký tự null.
Cách tiếp cận này chậm hơn khoảng 50 lần so với lặp lại thủ công với for ...(xem câu trả lời của Michael Aaron Safyan ) (3,55 giây so với 0,066 giây). Nhưng đối với các lệnh đầu vào khác như định vị, tìm, đọc từ tệp ( tr \\n \\0 <file) hoặc tương tự, bạn phải làm việc với xargsnhư thế này.
Kết quả tốt hơn cho tôi:
ls -1 | xargs -L1 -d "\n" CMD
find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 commandsẽ xử lý các trường hợp đầu ra của ls -1mơ hồ; sử dụng -printf '%P\0'thay vì -print0nếu bạn không muốn dẫn đầu ./về mỗi.
ls -1có thể là một ví dụ ở đây nhưng điều quan trọng cần nhớ là không tốt khi phân tích đầu ra củals. Xem: mywiki.wooledge.org/ParsingLs