Làm thế nào để bạn sử dụng chuyển hướng đầu ra kết hợp với tài liệu ở đây và con mèo?


56

Giả sử tôi có một tập lệnh mà tôi muốn chuyển sang lệnh khác hoặc chuyển hướng đến một tệp (chuyển sang shví dụ). Giả sử rằng tôi đang sử dụng bash.

Tôi có thể làm điều đó bằng cách sử dụng echo:

echo "touch somefile
echo foo > somefile" | sh

Tôi cũng có thể làm gần như điều tương tự bằng cách sử dụng cat:

cat << EOF
touch somefile
echo foo > somefile
EOF

Nhưng nếu tôi thay thế "EOF" bằng "EOF | sh" thì nó chỉ nghĩ rằng đó là một phần của di truyền.

Làm thế nào tôi có thể làm cho nó để catxuất văn bản từ stdin, và sau đó dẫn nó đến một vị trí tùy ý?


touchlà trừ khi có, chính xác những gì bạn muốn? chỉ đọc tệp đầu vào và chuyển hướng đến tệp khác với thiết bị xuất chuẩn?
Rahul Patil

2
@RahulPatil tất nhiên là vô dụng. Tôi chỉ muốn một ví dụ với nhiều hơn một dòng, để minh họa rõ hơn cho di truyền. Và nhìn vào ví dụ bằng cách sử dụng echo- tôi đã tự hỏi những gì tương đương với điều đó sẽ được sử dụng cat.
strugee

Ví dụ của bạn là tạo một shtập lệnh từ nhiều chuỗi và chuyển trực tiếp tới sh. Tôi thấy Q của bạn đang tìm cách chuyển đầu ra văn bản của nhiều lệnh, bao gồm cả tài liệu TẠI ĐÂY, trực tiếp đến một lệnh. Đó là những gì ví dụ thứ 2 của Ash làm.
Dave X

Câu trả lời:


91

Có nhiều cách để làm điều này. Đơn giản nhất có lẽ là thế này:

cat <<EOF | sh
touch somefile
echo foo > somefile
EOF

Một cái khác, đó là cú pháp đẹp hơn theo ý kiến ​​của tôi:

(
cat <<EOF
touch somefile
echo foo > somefile
EOF
) | sh

Điều này cũng hoạt động, nhưng không có subshell:

{
cat <<EOF
touch somefile
echo foo > somefile
EOF
} | sh

Nhiều biến thể hơn:

cat <<EOF |
touch somefile
echo foo > somefile
EOF
  sh

Hoặc là:

{ cat | sh; } << EOF
touch somefile
echo foo > somefile
EOF

Nhân tiện, tôi hy vọng việc sử dụng cattrong câu hỏi của bạn là một giữ chỗ cho một cái gì đó khác. Nếu không, hãy lấy nó ra, như thế này:

sh <<EOF
touch somefile
echo foo > somefile
EOF

Mà có thể được đơn giản hóa để này:

sh -c 'touch somefile; echo foo > somefile'

hoặc là:

sh -c 'touch somefile
echo foo > somefile'

Chuyển hướng đầu ra thay vì đường ống

sh >out <<EOF
touch somefile
echo foo > somefile
EOF

Sử dụng catđể có được tương đương với echo test > out:

cat >out <<EOF
test
EOF

Nhiều tài liệu ở đây

( cat; echo ---; cat <&3 ) <<EOF 3<<EOF2
hi
EOF
there
EOF2

Điều này tạo ra đầu ra:

hi
---
there

Đây là những gì đang xảy ra:

  • Shell nhìn thấy ( ... )và chạy các lệnh kèm theo trong một lớp con.
  • Con mèo và tiếng vang là đủ đơn giản. Việc cat <&3nói chạy mèo với mô tả tệp (fd) 0 (stdin) được chuyển hướng từ fd 3; nói cách khác, cat out đầu vào từ fd 3.
  • Trước khi (...)bắt đầu, shell nhìn thấy hai tài liệu ở đây chuyển hướng và thay thế fd 0 ( <<EOF) và fd 3 ( 3<<EOF2) với mặt đọc của ống
  • Khi lệnh ban đầu được khởi động, shell sẽ đọc stdin của nó cho đến khi đạt được EOF và gửi nó tới phía ghi của ống đầu tiên
  • Tiếp theo, nó cũng làm như vậy với EOF2 và phía ghi của ống thứ hai

đưa ra ví dụ từ thứ hai đến cuối cùng, bạn có thể đưa ra một ví dụ với chuyển hướng xuất sắc thay vì đường ống không?
strugee

Tôi đã chỉnh sửa câu trả lời bằng một ví dụ chuyển hướng; Đây có phải là hình thức bạn muốn chỉnh sửa? Nếu không, bạn có thể chỉ cho dòng đầu tiên của phần đó để làm rõ?
tro

1
Nó có thể giúp để hiểu làm thế nào vỏ xử lý này. Khi nó đánh giá dòng lệnh và tìm thấy << EOF, thì nó sẽ đọc từ đầu vào tiêu chuẩn cho đến khi một dòng chỉ có EOF được tìm thấy hoặc đầu vào cuối. Mọi thứ khác trên dòng lệnh gốc chưa được xử lý sau đó tiếp tục xử lý. Vì vậy, ví dụ, có thể làm một cái gì đó như thế này: (cat; echo ---; exec <&3; cat) <<EOF 3<<EOF2 >outvà sau đó đưa ra lệnh đầu vào đó với hai khối ở đây.
tro

Lời giải thích của bạn về xử lý vỏ rất thú vị nhưng trên đầu tôi :) Điều tôi muốn biết là cái gì sẽ cattương đương với echo test > out, sử dụng một di sản. Trong khi ví dụ đã cho của bạn đã thêm một chuyển hướng ở cuối đường ống.
strugee

1
@OlivierDulac - Tôi đã thêm ví dụ heredoc vào câu trả lời.
tro

1

Tôi chỉ muốn chỉ ra rằng việc sử dụng meowlà hợp lệ như EOF.

Kịch bản này sẽ nối Meow!vào một tệp có tên cat:

#!/bin/sh
cat <<meow>> cat
Meow!
meow

Lưu dưới dạng catsvà làm cho nó có thể thực thi được chmod +x cats, sau đó chạy với ./cats:

$ ./cats
$ cat cat
Meow!
$ ./cats
$ cat cat
Meow!
Meow!

Giải trình:

  • cat <<meowlà cú pháp tài liệu ở đây . Nó ra lệnh cho kịch bản chọn khối văn bản theo dòng này, cho đến khi gặp chuỗi meow. Các nội dung sau đó sẽ được xuất ra (hoặc được dẫn dọc).
  • >> catống dẫn đến tập tin có tên cat.
  • Sử dụng >thay vì >>sẽ ghi đè lên tập tin thay vì nối thêm vào nó.
  • Meow!là nội dung của tài liệu ở đây .
  • meowlà điểm đánh dấu kết thúc cho tài liệu ở đây . Các nội dung, với việc sử dụng >>, được thêm vào cat.

Đường ống dẫn đến thiết bị xuất chuẩn và tệp:

Để làm đường ống bạn yêu cầu, không có tài liệu ở đây là bắt buộc.

catkhông thể cả văn bản đầu ra và chuyển văn bản theo, nhưng teelà một kết hợp hoàn hảo cho những gì bạn đang yêu cầu:

echo echo | tee tee

Điều này sẽ xuất cả chuỗi echovà ghi echovào một tệp có tên tee.

Bạn cũng có thể chuyển đầu ra qua cat, nếu đó là một phần của yêu cầu, với:

echo echo | tee tee | cat </dev/stdin

Hoặc chỉ:

echo echo | tee tee | cat

Nội dung của tập tin:

$ cat tee
echo

1
Điều này không thực sự trả lời câu hỏi. Cũng >không tạo đường ống như viên đạn cuối cùng của bạn ngụ ý.
strugee

2
@strugee, >có thể tạo các đường ống zshkhi cùng một fd được chuyển hướng nhiều lần như trong echo foo >&1 > teehoặc echo foo > tee | cat, trong đó zshthực hiện một nội bộ teeđể cung cấp đầu ra echocho cả hai catteetệp.
Stéphane Chazelas

Cập nhật câu trả lời của tôi để trả lời tốt hơn câu hỏi.
Alexander
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.