Gửi chuỗi tới stdin


157

Có cách nào để làm điều này một cách hiệu quả trong bash:

/my/bash/script < echo 'This string will be sent to stdin.'

Tôi biết rằng tôi có thể dẫn đầu ra từ tiếng vang như thế này:

echo 'This string will be piped to stdin.' | /my/bash/script

1
Bạn có ý nghĩa gì bởi hiệu quả , tại sao không phải là một cách để làm điều này?
Andy

Cả hai lệnh bạn liệt kê nên thực hiện chính xác cùng một điều. Bạn gặp vấn đề gì?
Flimzy

5
@Flimzy: afaik, cái đầu tiên sẽ không hoạt động như mong đợi, nó sẽ cố mở một tệp có tênecho
Andy

Ô đúng rồi. Vì vậy, những gì sai với hình thức thứ hai?
Flimzy

2
@Flimzy: bên cạnh đó, >biểu mẫu chuyển hướng sẽ mở một mô tả tệp dưới dạng fd 0(stdin), trong khi |mở bắt đầu một tiến trình con và gắn stdout (fd 1) vào stdin của tiến trình khác. Thực tế này có thể có những hậu quả không hề nhỏ (nghĩ về việc chia sẻ các biến môi trường?)
sehe

Câu trả lời:


261

Bạn có thể sử dụng một dòng heredoc

cat <<< "This is coming from the stdin"

ở trên giống như

cat <<EOF
This is coming from the stdin
EOF

hoặc bạn có thể chuyển hướng đầu ra từ một lệnh, như

diff <(ls /bin) <(ls /usr/bin)

hoặc bạn có thể đọc như

while read line
do
   echo =$line=
done < some_file

hoặc đơn giản

echo something | read param

Và làm thế nào để nhập giá trị nhị phân theo cách này? Không sử dụng đường ống (tôi biết có thể thực hiện với đường ống như sau echo -e "\x01\x02..." | ./script:)
cprcrack

Tôi thích viết nó theo cách khác: <<< "Điều này đến từ stdin" perl ..., cách này trông giống như phía bên trái của đường ống.
Pyrolistic

@Pyrolistic có! Đặc biệt hữu ích khi thành thạo ví dụ một pereliner perliner từ một dòng lệnh - dễ dàng chỉnh sửa các đối số của perl mà không cần nhiều chuyển động lùi với một con trỏ. :)
jm666

@ jm666 điều đáng buồn là tôi đã học được ngày hôm qua nếu bạn sử dụng bí danh bash, bạn chỉ cần sử dụng mẫu lệnh_alias <<< "chuỗi stdin", nếu không nó sẽ nói lệnh không được tìm thấy
Pyrolistic

@ jm666 Có nơi nào tôi có thể tìm hiểu thêm về <<<? Tôi xấu hổ khi thừa nhận rằng tôi chưa bao giờ nhìn thấy nó trước đây, và tôi hoàn toàn bị nó làm cho bối rối. Tôi đã thử Googling cho nó, nhưng kết quả của tôi không liên quan.
wpcarro

66

Bạn đã gần

/my/bash/script <<< 'This string will be sent to stdin.'

Đối với đầu vào đa dòng, tài liệu ở đây phù hợp:

/my/bash/script <<STDIN -o other --options
line 1
line 2
STDIN

Chỉnh sửa để bình luận:

Để đạt được đầu vào nhị phân, nói

xxd -r -p <<BINARY | iconv -f UCS-4BE -t UTF-8 | /my/bash/script
0000 79c1 0000 306f 0000 3061 0000 3093 0000 3077 0000 3093 0000 304b 0000 3093 0000 3077 0000 3093 0000 306a 0000 8a71 0000 306b 0000 30ca 0000 30f3 0000 30bb
0000 30f3 0000 30b9 0000 3092 0000 7ffb 0000 8a33 0000 3059 0000 308b 0000 3053 0000 3068 0000 304c 0000 3067 0000 304d 0000 000a
BINARY

Nếu bạn thay thế catcho /my/bash/script(hoặc thực sự thả ống cuối cùng), bản in này:

私はちんぷんかんぷんな話にナンセンスを翻訳することができ

Hoặc, nếu bạn muốn một cái gì đó táo bạo hơn một chút:

0000000: 0000 0000 bef9 0e3c 59f8 8e3c 0a71 d63c  .......<Y..<.q.<
0000010: c6f2 0e3d 3eaa 323d 3a5e 563d 090e 7a3d  ...=>.2=:^V=..z=
0000020: 7bdc 8e3d 2aaf a03d b67e b23d c74a c43d  {..=*..=.~.=.J.=
0000030: 0513 d63d 16d7 e73d a296 f93d a8a8 053e  ...=...=...=...>
0000040: 6583 0e3e 5a5b 173e 5b30 203e 3d02 293e  e..>Z[.>[0 >=.)>
0000050: d4d0 313e f39b 3a3e 6f63 433e 1c27 4c3e  ..1>..:>ocC>.'L>
0000060: cde6 543e 59a2 5d3e 9259 663e 4d0c 6f3e  ..T>Y.]>.Yf>M.o>
0000070: 60ba 773e cf31 803e ee83 843e 78d3 883e  `.w>.1.>...>x..>
0000080: 5720 8d3e 766a 913e beb1 953e 1cf6 993e  W .>vj.>...>...>
0000090: 7a37 9e3e c275 a23e dfb0 a63e bce8 aa3e  z7.>.u.>...>...>
00000a0: 441d af3e 624e b33e 017c b73e 0ca6 bb3e  D..>bN.>.|.>...>
00000b0: 6fcc bf3e 15ef c33e e90d c83e d728 cc3e  o..>...>...>.(.>
00000c0: c93f d03e ac52 d43e 6c61 d83e f36b dc3e  .?.>.R.>la.>.k.>
00000d0: 2f72 e03e 0a74 e43e 7171 e83e 506a ec3e  /r.>.t.>qq.>Pj.>
00000e0: 945e f03e 274e f43e f738 f83e f11e fc3e  .^.>'N.>.8.>...>
00000f0: 0000 003f 09ee 013f 89d9 033f 77c2 053f  ...?...?...?w..?
0000100: caa8 073f 788c 093f 776d 0b3f be4b 0d3f  ...?x..?wm.?.K.?
0000110: 4427 0f3f 0000 113f e8d5 123f f3a8 143f  D'.?...?...?...?
0000120: 1879 163f 4e46 183f 8d10 1a3f cad7 1b3f  .y.?NF.?...?...?
0000130: fe9b 1d3f 1f5d 1f3f 241b 213f 06d6 223f  ...?.].?$.!?.."?
0000140: bb8d 243f 3a42 263f 7cf3 273f 78a1 293f  ..$?:B&?|.'?x.)?
0000150: 254c 2b3f 7bf3 2c3f 7297 2e3f 0138 303f  %L+?{.,?r..?.80?
0000160: 22d5 313f ca6e 333f                      ".1?.n3?

Đó là mức phạt 90 độ đầu tiên trong phao nhị phân 4byte


Và làm thế nào để nhập giá trị nhị phân theo cách này?
cprcrack

Tôi sẽ sử dụng xxd -r(hoặc od) để lọc tài liệu TẠI ĐÂY
sehe

Bạn có thể giải thích nó với một ví dụ? Tôi đã không quản lý để làm điều đó.
cprcrack

1
xem câu trả lời chỉnh sửa. Vấn đề là không bao gồm dữ liệu nhị phân thô trong tập lệnh của bạn, mà thay vào đó, lọc nó thông qua một chương trình như
xxd

Quan điểm của việc thực hiện là gì: "/ my / bash / script <<< 'Chuỗi này sẽ được gửi tới stdin.'" Khi bạn có thể nói trực tiếp: "/ my / bash / script 'Chuỗi này sẽ được gửi đến stdin. '"?
Baiyan Huang

2

Bạn cũng có thể sử dụng readnhư thế này

echo "enter your name"
read name
echo $name

2

Giải pháp

Bạn muốn (1) tạo đầu ra xuất chuẩn trong một quy trình (như echo '…') và (2) chuyển hướng đầu ra đó sang đầu vào stdin của quy trình khác nhưng (3) mà không sử dụng cơ chế ống bash. Đây là một giải pháp phù hợp với cả ba điều kiện:

/my/bash/script < <(echo 'This string will be sent to stdin.')

Đây <là chuyển hướng đầu vào bình thường cho stdin. Là <(…)thay thế quá trình bash. Roughly nó tạo ra một /dev/fd/…tập tin với đầu ra của lệnh thay thế và chuyển tên tệp đó thay cho <(…), dẫn đến đây, ví dụ ở đây script < /dev/fd/123. Để biết chi tiết, xem câu trả lời này

So sánh với các giải pháp khác

  • Một heredoc một dòng được gửi đến stdin script <<< 'string'chỉ cho phép gửi các chuỗi tĩnh, không cho đầu ra của các lệnh khác.

  • Thay thế quá trình một mình, chẳng hạn như trong diff <(ls /bin) <(ls /usr/bin), không gửi bất cứ điều gì cho stdin. Thay vào đó, quá trình đầu ra được thông qua dưới dạng nội dung của các tệp được tạo trong nền, tương đương với ví dụ diff /dev/fd/10 /dev/fd/11. Trong lệnh đó, diffkhông nhận được đầu vào từ stdin.

Trường hợp sử dụng

Tôi thích điều đó, không giống như cơ chế đường ống, < <(…)cơ chế cho phép đặt lệnh trước và tất cả đầu vào sau nó, như là tiêu chuẩn cho đầu vào từ các tùy chọn dòng lệnh.

Tuy nhiên, ngoài thẩm mỹ dòng lệnh, có một số trường hợp không thể sử dụng cơ chế đường ống. Ví dụ, khi một lệnh nhất định phải được cung cấp làm đối số cho lệnh khác, chẳng hạn như trong ví dụ này vớisshpass .


Thú vị thay thế. Điều này có xảy ra để tuân thủ POSIX không giống như <<<?
Tất cả công nhân là cần thiết

0
cat | /my/bash/script

Cho phép một người nhập nhiều dòng vào một chương trình, mà không có đầu vào nào được lưu trong lịch sử, cũng không hiển thị trong đó ps. Chỉ cần nhấn Ctrl + C khi nhập xong để kết thúc cat.


-1

bí danh có thể và không thể xử lý đường ống ...

Ở đây chúng tôi tạo ra 3 dòng đầu ra

$ echo -e "line 1\nline 2\nline 3"
line 1
line 2
line 3

Sau đó, chúng tôi dẫn đầu ra tới stdin của lệnh sed để đặt tất cả chúng trên một dòng

$ echo -e "line 1\nline 2\nline 3" |  sed -e ":a;N;\$!ba ;s?\n? ?g"
line 1 line 2 line 3

Nếu chúng ta định nghĩa một bí danh của cùng một lệnh sed

$ alias oline='sed -e ":a;N;\$!ba ;s?\n? ?g"'

Chúng ta có thể dẫn đầu ra tới stdin của bí danh và nó hoạt động giống hệt nhau

$ echo -e "line 1\nline 2\nline 3" |  oline
line 1 line 2 line 3

Vấn đề phát sinh khi chúng ta cố gắng xác định bí danh là một hàm

$ alias oline='function _oline(){ sed -e ":a;N;\$!ba ;s?\n? ?g";}_oline'

Xác định bí danh là một funstion phá vỡ đường ống

$ echo -e "line 1\nline 2\nline 3" |  oline
>

Thứ nhất, điều này không trả lời câu hỏi - có thể bạn đã trả lời sai câu hỏi? Thứ hai, tại sao bạn lại định nghĩa một hàm bên trong bí danh? Bạn chỉ nên làm function oline() { sed -e ":a;N;\$!ba ;s?\n? ?g"; }. Thứ ba, chiếc sed này sẽ dễ hiểu hơn rất nhiều với awk:awk -F '\n' 'ORS=" " { print } END { printf "\n"}'
Leonardo Dagnino
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.