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 -L
cờ đả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. [...]
ls
tự động làm -1
trong một đường ống.
ls | xargs -L2 echo
và 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.
xargs
chỉ 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 read
trong một vòng lặp.
-L1
là 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 found
Có vẻ như nó lấy e
tiếng vang là lệnh sed hay gì đó.
while
vò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 sed
lệ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 read
gây rối với các ký tự thoát. Ví dụ echo '"a \"nested\" quote"' | while read line; do echo "$line"; done
cho "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"; done
chú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
cmd
có 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 -1
chấm dứt các mục với các ký tự dòng mới, do đó tr
chuyể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 xargs
như 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 command
sẽ xử lý các trường hợp đầu ra của ls -1
mơ hồ; sử dụng -printf '%P\0'
thay vì -print0
nếu bạn không muốn dẫn đầu ./
về mỗi.
ls -1
có 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