Làm thế nào để có được hộp thoại đầu vào hướng đến một biến?


18

Tôi đã tự dạy mình bash scripting và đã gặp phải một vấn đề. Tôi đã viết một tập lệnh để lấy đầu vào từ người dùng, sử dụng lệnh 'đọc' và biến đầu vào đó thành một biến để sử dụng sau này trong tập lệnh. Kịch bản hoạt động, nhưng ....

Tôi muốn có thể thiết lập nó bằng 'hộp thoại'. Tôi phát hiện ra rằng

'Hộp thoại --inputbox' sẽ hướng đầu ra tới 'stderr' và để có được đầu vào đó dưới dạng một biến, bạn phải hướng nó đến một tệp và sau đó truy xuất nó. Mã tôi tìm thấy để giải thích điều này là:

#!/bin/bash
dialog --inputbox \

"What is your username?" 0 0 2> /tmp/inputbox.tmp.$$

retval=$?

input=`cat /tmp/inputbox.tmp.$$`

rm -f /tmp/inputbox.tmp.$$

case $retval in
0)

echo "Your username is '$input'";;
1)

echo "Cancel pressed.";;

esac

Tôi thấy rằng nó đang gửi sdterr đến /tmp/inputbox.tmp.$$ với 2>, nhưng tệp đầu ra trông giống như 'inputbox.tmp.21661'. Khi tôi thử và gửi tệp, nó sẽ báo lỗi. Vì vậy, tôi vẫn không thể lấy đầu vào của người dùng từ --inputbox làm biến.

Kịch bản mẫu:

echo "  What app would you like to remove? "

read dead_app

sudo apt-get remove --purge $dead_app

Vì vậy, như bạn có thể thấy nó là một kịch bản cơ bản. Thậm chí có thể lấy biến là một từ dialog --inputbox?


Theo kinh nghiệm của tôi, kịch bản hoạt động tốt, nếu bạn loại bỏ dòng trống sau dòng thứ 2. Ngoài ra, bạn có thể sử dụng mktemplệnh để tạo một tệp tạm thời.
jarno

Câu trả lời:


16

: DI không thể giải thích nó !!! Nếu bạn có thể hiểu những gì họ đang nói trong Hướng dẫn về Bash-Scripting nâng cao: Chương 20. Chuyển hướng I / O , hãy viết câu trả lời mới và tôi sẽ cung cấp cho bạn 50rep :

exec 3>&1;
result=$(dialog --inputbox test 0 0 2>&1 1>&3);
exitcode=$?;
exec 3>&-;
echo $result $exitcode;

Tham khảo: Hộp thoại trong bash không lấy đúng biến

^ câu trả lời từ @Sneetsher (ngày 4 tháng 7 năm 2014)

Theo yêu cầu, tôi sẽ cố gắng giải thích những gì đoạn trích này đang làm từng dòng một.

Lưu ý rằng tôi sẽ đơn giản hóa nó bằng cách bỏ qua tất cả các ;dấu chấm phẩy ở cuối dòng, bởi vì chúng không cần thiết nếu chúng ta viết một lệnh trên mỗi dòng.

I / O - Luồng:

Đầu tiên, bạn cần hiểu các luồng giao tiếp. Có 10 luồng, được đánh số từ 0 đến 9:

  • Luồng 0 ("STDIN"):
    "Đầu vào tiêu chuẩn", luồng đầu vào mặc định để đọc dữ liệu từ bàn phím.

  • Luồng 1 ("STDOUT"):
    "Đầu ra tiêu chuẩn", luồng đầu ra mặc định được sử dụng để hiển thị văn bản bình thường trong thiết bị đầu cuối.

  • Luồng 2 ("STDERR"): "Lỗi tiêu chuẩn", luồng đầu ra mặc định được sử dụng để hiển thị lỗi hoặc văn bản khác cho các mục đích đặc biệt trong thiết bị đầu cuối.

  • Luồng 3-9:
    Các luồng bổ sung, có thể sử dụng tự do. Chúng không được sử dụng theo mặc định và không tồn tại cho đến khi một cái gì đó cố gắng sử dụng chúng.

Lưu ý rằng tất cả các "luồng" được thể hiện bên trong bởi các mô tả tệp trong /dev/fd(là một liên kết tượng trưng /proc/self/fdchứa một liên kết tượng trưng khác cho mỗi luồng ... nó hơi phức tạp và không quan trọng đối với hành vi của chúng, vì vậy tôi dừng ở đây.). Các dòng tiêu chuẩn cũng có /dev/stdin, /dev/stdout/dev/stderr(là liên kết tượng trưng một lần nữa, vv ...).

Kịch bản:

  • exec 3>&1

    Bash tích hợp execcó thể được sử dụng để áp dụng chuyển hướng luồng cho shell, điều đó có nghĩa là nó ảnh hưởng đến tất cả các lệnh sau. Để biết thêm thông tin, chạy help exectrong thiết bị đầu cuối của bạn.

    Trong trường hợp đặc biệt này, luồng 3 được chuyển hướng đến luồng 1 (STDOUT), điều đó có nghĩa là mọi thứ chúng tôi gửi đến luồng 3 sau sẽ xuất hiện trong thiết bị đầu cuối của chúng tôi như thể nó thường được in sang STDOUT.

  • result=$(dialog --inputbox test 0 0 2>&1 1>&3)

    Dòng này bao gồm nhiều phần và cấu trúc cú pháp:

    • result=$(...)
      Cấu trúc này thực thi lệnh trong ngoặc và gán đầu ra (STDOUT) cho biến bash result. Nó có thể đọc được thông qua $result. Tất cả điều này được mô tả bằng cách nào đó trong looong veeeery man bash.

    • dialog --inputbox TEXT HEIGHT WIDTH
      Lệnh này hiển thị hộp TUI với văn bản đã cho, trường nhập văn bản và hai nút OK và CANCEL. Nếu OK được chọn, lệnh sẽ thoát với trạng thái 0 và in văn bản đã nhập vào STDERR, nếu CANCEL được chọn, nó sẽ thoát với mã 1 và không in gì. Để biết thêm thông tin, đọc man dialog.

    • 2>&1 1>&3
      Đây là hai lệnh chuyển hướng. Chúng sẽ được giải thích từ phải sang trái:

      1>&3 chuyển hướng luồng 1 của lệnh (STDOUT) sang luồng tùy chỉnh 3.

      2>&1 sau đó chuyển hướng luồng 2 của lệnh (STDERR) sang luồng 1 (STDOUT).

      Điều đó có nghĩa là tất cả mọi thứ lệnh in ra STDOUT hiện xuất hiện trong luồng 3, trong khi mọi thứ được dự định hiển thị trên STDERR giờ được chuyển hướng đến STDOUT.

    Vì vậy, toàn bộ dòng hiển thị một dấu nhắc văn bản (trên STDOUT, được chuyển hướng đến luồng 3, phần vỏ lại chuyển hướng trở lại STDOUT ở cuối - xem exec 3>&1lệnh) và gán dữ liệu đã nhập (được trả về qua STDERR, sau đó được chuyển hướng đến STDOUT) đến biến Bash result.

  • exitcode=$?

    Mã này lấy mã thoát của lệnh đã thực hiện trước đó (ở đây từ dialog) thông qua biến Bash dành riêng $?(luôn giữ mã thoát cuối cùng) và chỉ cần lưu nó trong biến Bash của chính chúng ta exitcode. Nó có thể được đọc qua $exitcodemột lần nữa. Bạn có thể tìm kiếm thêm thông tin về điều này man bash, nhưng có thể mất một lúc ...

  • exec 3>&-

    Bash tích hợp execcó thể được sử dụng để áp dụng chuyển hướng luồng cho shell, điều đó có nghĩa là nó ảnh hưởng đến tất cả các lệnh sau. Để biết thêm thông tin, chạy help exectrong thiết bị đầu cuối của bạn.

    Trong trường hợp đặc biệt này, luồng 3 được chuyển hướng đến "luồng -", điều đó chỉ có nghĩa là nó sẽ bị đóng. Dữ liệu được gửi đến luồng 3 sẽ không được chuyển hướng ở bất kỳ đâu kể từ bây giờ.

  • echo $result $exitcode

    Lệnh đơn giản này echo(có thêm thông tin về man echo) chỉ in nội dung của hai biến Bash resultexitcodetới STDOUT. Vì chúng tôi không còn chuyển hướng dòng rõ ràng hoặc ẩn ở đây nữa, chúng sẽ thực sự xuất hiện trên STDOUT và do đó chỉ đơn giản là được hiển thị trong thiết bị đầu cuối. Thật là một phép lạ! ;-)

Tóm lược:

Đầu tiên, chúng tôi thiết lập hệ vỏ để chuyển hướng mọi thứ chúng tôi gửi đến luồng tùy chỉnh 3 trở lại STDOUT, để nó hiển thị trong thiết bị đầu cuối của chúng tôi.

Sau đó, chúng tôi chạy dialoglệnh, chuyển hướng STDOUT ban đầu của nó sang luồng tùy chỉnh 3 của chúng tôi, vì cuối cùng nó cần được hiển thị, nhưng chúng tôi tạm thời cần sử dụng luồng STDOUT cho thứ khác.
Chúng tôi chuyển hướng STDERR ban đầu của lệnh, nơi đầu vào của người dùng cửa sổ hội thoại được trả về, sau đó đến STDOUT.
Bây giờ chúng ta có thể chụp STDOUT (chứa dữ liệu được chuyển hướng từ STDERR) và lưu trữ nó trong biến của chúng ta $result. Nó chứa đầu vào người dùng mong muốn ngay bây giờ!

Chúng tôi cũng muốn dialogmã thoát của lệnh, cho chúng tôi biết liệu OK hay CANCEL đã được bấm. Giá trị này được trình bày trong biến Bash dành riêng $?và chúng tôi chỉ sao chép nó vào biến của chính chúng tôi $exitcode.

Sau đó, chúng tôi đóng luồng 3 lần nữa, vì chúng tôi không cần nó nữa, để ngăn chặn các chuyển hướng tiếp theo của nó.

Cuối cùng, chúng ta thường xuất nội dung của cả hai biến $result(đầu vào người dùng của cửa sổ hội thoại) và $exitcode(0 cho OK, 1 cho CANCEL) cho thiết bị đầu cuối.


Tôi nghĩ rằng việc sử dụng execlà phức tạp không cần thiết. Tại sao không chỉ chúng tôi --stdouttùy chọn cho dialoghoặc chuyển hướng đầu ra của nó bằng cách 2>&1 >/dev/tty?
jarno

Xin vui lòng xem câu trả lời của tôi .
jarno

3
Câu trả lời chính xác! Tuy nhiên, tôi tin rằng bạn có một lưu ý không chính xác - bạn nói rằng "Chúng sẽ được giải thích từ phải sang trái" nhưng tôi tin rằng điều đó không đúng. Từ hướng dẫn bash gnu.org/software/bash/manual/html_node/Redirections.html nó chỉ ra rằng các chuyển hướng diễn ra khi chúng gặp phải (tức là từ trái sang phải)
ralfthewise

14

Sử dụng các công cụ riêng của hộp thoại: cờ --output-fd

Nếu bạn đọc trang man cho hộp thoại, có tùy chọn --output-fd, cho phép bạn đặt rõ ràng nơi đầu ra đi (STDOUT 1, STDERR 2), thay vì theo mặc định sẽ chuyển sang STDERR.

Dưới đây bạn có thể thấy tôi đang chạy dialoglệnh mẫu , với tuyên bố rõ ràng rằng đầu ra phải đi đến mô tả tệp 1, cho phép tôi lưu nó vào MYVAR.

MYVAR=$(dialog --inputbox "THIS OUTPUT GOES TO FD 1" 25 25 --output-fd 1)

nhập mô tả hình ảnh ở đây

Sử dụng ống có tên

Phương pháp thay thế có nhiều tiềm năng tiềm ẩn, là sử dụng một cái gì đó được gọi là ống dẫn .

#!/bin/bash

mkfifo /tmp/namedPipe1 # this creates named pipe, aka fifo

# to make sure the shell doesn't hang, we run redirection 
# in background, because fifo waits for output to come out    
dialog --inputbox "This is an input box  with named pipe" 40 40 2> /tmp/namedPipe1 & 

# release contents of pipe
OUTPUT="$( cat /tmp/namedPipe1  )" 


echo  "This is the output " $OUTPUT
# clean up
rm /tmp/namedPipe1 

nhập mô tả hình ảnh ở đây

Tổng quan sâu hơn về câu trả lời của user.dz với cách tiếp cận thay thế

Câu trả lời ban đầu của user.dz và ByteCommander giải thích rằng cả hai đều cung cấp một giải pháp tốt và tổng quan về những gì nó làm. Tuy nhiên, tôi tin rằng một phân tích sâu hơn có thể có lợi để giải thích tại sao nó hoạt động.

Trước hết, điều quan trọng là phải hiểu hai điều: vấn đề chúng ta đang cố gắng giải quyết là gì và hoạt động cơ bản của các cơ chế vỏ mà chúng ta đang giải quyết là gì. Nhiệm vụ là bắt đầu ra của lệnh thông qua thay thế lệnh. Theo tổng quan đơn giản mà mọi người đều biết, các lệnh thay thế nắm bắt stdoutlệnh và để nó được sử dụng lại bởi một thứ khác. Trong trường hợp này, result=$(...)phần nên lưu đầu ra của bất kỳ lệnh nào được chỉ định bởi ...một biến được gọi result.

Bên dưới mui xe, việc thay thế lệnh thực sự được thực hiện dưới dạng đường ống, trong đó có một tiến trình con (lệnh thực tế chạy) và quá trình đọc (giúp lưu đầu ra vào biến). Điều này là hiển nhiên với một dấu vết đơn giản của các cuộc gọi hệ thống. Lưu ý rằng mô tả tập tin 3 là đầu đọc của ống, trong khi 4 là đầu ghi. Đối với tiến trình con của echo, ghi vào stdoutbộ mô tả tệp 1, bộ mô tả tệp đó thực sự là bản sao của bộ mô tả tệp 4, là đầu ghi của đường ống. Lưu ý rằng stderrkhông đóng vai trò ở đây, đơn giản vì đó chỉ là một đường ống kết nối stdout.

$ strace -f -e pipe,dup2,write,read bash -c 'v=$(echo "X")'
...
pipe([3, 4])                            = 0
strace: Process 6200 attached
[pid  6199] read(3,  <unfinished ...>
[pid  6200] dup2(4, 1)                  = 1
[pid  6200] write(1, "X\n", 2 <unfinished ...>
[pid  6199] <... read resumed> "X\n", 128) = 2
[pid  6200] <... write resumed> )       = 2
[pid  6199] read(3, "", 128)            = 0
[pid  6200] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=6200, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++

Chúng ta hãy quay lại câu trả lời ban đầu trong một giây. Vì bây giờ chúng ta biết rằng dialogviết hộp TUI stdout, trả lời stderrvà trong khi thay thế lệnh stdoutđược chuyển sang một nơi khác, chúng ta đã có một phần của giải pháp - chúng ta cần phải viết lại các mô tả tệp theo cách đó stderrsẽ được chuyển đến quy trình đọc. Đây là 2>&1một phần của câu trả lời. Tuy nhiên, chúng ta làm gì với hộp TUI?

Đó là nơi mô tả tệp 3 xuất hiện. Tòa nhà dup2()cho phép chúng tôi sao chép mô tả tệp, làm cho chúng tham chiếu hiệu quả đến cùng một vị trí, nhưng chúng tôi có thể thao tác chúng một cách riêng biệt. Mô tả tập tin của các quá trình có thiết bị đầu cuối điều khiển gắn thực sự trỏ đến thiết bị đầu cuối cụ thể. Điều này là hiển nhiên nếu bạn làm

$ ls -l /proc/self/fd
total 0
lrwx------ 1 user1 user1 64 Aug 20 10:30 0 -> /dev/pts/5
lrwx------ 1 user1 user1 64 Aug 20 10:30 1 -> /dev/pts/5
lrwx------ 1 user1 user1 64 Aug 20 10:30 2 -> /dev/pts/5
lr-x------ 1 user1 user1 64 Aug 20 10:30 3 -> /proc/6424/fd

/dev/pts/5thiết bị đầu cuối giả hiện tại của tôi ở đâu . Do đó, nếu bằng cách nào đó chúng ta có thể lưu điểm đến này, chúng ta vẫn có thể ghi hộp TUI lên màn hình thiết bị đầu cuối. Đó là những gì exec 3>&1. command > /dev/nullVí dụ, khi bạn gọi một lệnh với chuyển hướng , shell sẽ chuyển qua bộ mô tả tệp stdout của nó và sau đó sử dụng dup2()để ghi bộ mô tả tệp đó vào /dev/null. Các execlệnh Thực hiện một cái gì đó tương tự nhưdup2() mô tả file cho phiên toàn vỏ, do đó làm cho bất kỳ lệnh kế thừa mô tả tập tin đã chuyển hướng. Tương tự với exec 3>&1. Bộ mô tả tệp 3bây giờ sẽ tham chiếu / trỏ đến thiết bị đầu cuối kiểm soát và bất kỳ lệnh nào chạy trong phiên shell đó sẽ biết về nó.

Vì vậy, khi result=$(dialog --inputbox test 0 0 2>&1 1>&3);xảy ra, shell tạo một ống để hộp thoại để ghi, nhưng 2>&1trước tiên cũng sẽ làm cho bộ mô tả tệp của lệnh 2 được sao chép vào bộ mô tả tệp ghi của ống đó (do đó làm cho đầu ra đi đến đầu đọc của ống và vào biến) , trong khi bộ mô tả tệp 1 sẽ được sao chép lên 3. Điều này sẽ làm cho bộ mô tả tệp 1 vẫn tham chiếu đến thiết bị đầu cuối kiểm soát và hộp thoại TUI sẽ hiển thị trên màn hình.

Bây giờ, thực sự có một tay ngắn cho thiết bị đầu cuối kiểm soát hiện tại của quá trình, đó là /dev/tty. Do đó, giải pháp có thể được đơn giản hóa mà không cần sử dụng các mô tả tệp, chỉ cần vào:

result=$(dialog --inputbox test 0 0 2>&1 1>/dev/tty);
echo "$result"

Những điều quan trọng cần nhớ:

  • mô tả tập tin được kế thừa từ shell bởi mỗi lệnh
  • thay thế lệnh được thực hiện như đường ống
  • bộ mô tả tệp trùng lặp sẽ tham chiếu đến cùng một nơi với bản gốc, nhưng chúng ta có thể thao tác riêng từng bộ mô tả tệp

Xem thêm


Trang này cũng nói rằng --stdouttùy chọn đó có thể nguy hiểm và dễ bị lỗi trên một số hệ thống, và tôi nghĩ --output-fd 1là đang làm như vậy: --stdout: Direct output to the standard output. This option is provided for compatibility with Xdialog, however using it in portable scripts is not recommended, since curses normally writes its screen updates to the standard output. If you use this option, dialog attempts to reopen the terminal so it can write to the display. Depending on the platform and your environment, that may fail.- Tuy nhiên, ý tưởng đường ống có tên là tuyệt vời!
Chỉ huy Byte

@ByteCommander "Có thể thất bại" không phải là rất thuyết phục, vì điều này không cung cấp ví dụ. Ngoài ra, họ không đề cập bất cứ điều gì về --output-fd, đó là tùy chọn tôi đã sử dụng ở đây, không phải --stdout. Thứ hai, hộp thoại đang được vẽ trên thiết bị xuất chuẩn đầu tiên, đầu ra được trả về là thứ hai. Chúng tôi không làm hai việc này cùng một lúc. Tuy nhiên, --output-fd không đặc biệt yêu cầu một người sử dụng fd 1 (STDOUT). Nó có thể dễ dàng được chuyển hướng đến một mô tả tập tin khác
Sergiy Kolodyazhnyy

Tôi không chắc chắn, có thể nó hoạt động ở mọi nơi, có thể nó chỉ hoạt động trên hầu hết các hệ thống. Nó hoạt động trên máy của tôi và trang này nói rằng sử dụng một tùy chọn tương tự một cách thận trọng là tất cả những gì tôi biết chắc chắn. Nhưng như tôi đã nói, +1 dù sao cũng xứng đáng với các đường ống được đặt tên.
Chỉ huy Byte

Tôi nên bình luận ở đây, để giữ một số cân bằng. Đối với tôi, đây có thể là câu trả lời chính tắc trực tiếp duy nhất (1) nó chỉ sử dụng cùng một công cụ và nó đã thực hiện các tùy chọn mà không có bất kỳ công cụ bên ngoài nào (2) Nó hoạt động trong Ubuntu và tất cả những gì AU nói về. : / thật đáng buồn khi OP dường như từ bỏ câu hỏi này.
user.dz

Lợi thế của việc sử dụng ống có tên thay vì tập tin thông thường ở đây là gì? Bạn không muốn xóa đường ống sau khi sử dụng?
jarno

7

: DI không thể giải thích nó !!! Nếu bạn có thể hiểu những gì họ đang nói trong tài liệu tham khảo: Hướng dẫn về Bash-Scripting nâng cao: Chương 20. Chuyển hướng I / O , hãy viết câu trả lời mới và tôi sẽ cung cấp cho bạn 50rep

Bounty đã được đưa ra, để giải thích, xem câu trả lời của ByteCommander . :) Đây là một phần của lịch sử.

exec 3>&1;
result=$(dialog --inputbox test 0 0 2>&1 1>&3);
exitcode=$?;
exec 3>&-;
echo $result $exitcode;

Nguồn: Hộp thoại trong bash không lấy đúng biến
Tham khảo: Bash nâng cao - Hướng dẫn về kịch bản: Chương 20. Chuyển hướng I / O


đề nghị đó vẫn còn hiệu lực? Tôi nghĩ rằng tôi có thể giải thích những gì bạn tìm thấy ở đó một năm rưỡi trước ... :-)
Chỉ huy Byte

@ByteCommander, tuy nhiên nếu bạn có thể cung cấp điều đó, tôi sẽ cung cấp cho bạn điều đó, tôi sẽ nói theo cách của tôi: D.
user.dz

@ByteCommander, làm ơn, ping tôi sau khi bạn đăng nó.
user.dz

1
Đã kết thúc! Askubfox.com/a/704616/367990 Tôi hy vọng bạn hiểu mọi thứ và tận hưởng "Eureka!" chốc lát. :-D Để lại một bình luận nếu không có gì rõ ràng.
Chỉ huy Byte

4

Điều này làm việc cho tôi:

#!/bin/bash
input=$(dialog --stdout --inputbox "What is your username?" 0 0)
retval=$?

case $retval in
${DIALOG_OK-0}) echo "Your username is '$input'.";;
${DIALOG_CANCEL-1}) echo "Cancel pressed.";;
${DIALOG_ESC-255}) echo "Esc pressed.";;
${DIALOG_ERROR-255}) echo "Dialog error";;
*) echo "Unknown error $retval"
esac

Trang hướng dẫn dialognói về --stdout:

Đầu ra trực tiếp đến đầu ra tiêu chuẩn. Tùy chọn này được cung cấp để tương thích với Xdialog, tuy nhiên không nên sử dụng nó trong các tập lệnh di động, vì lời nguyền thường ghi các cập nhật màn hình của nó vào đầu ra tiêu chuẩn. Nếu bạn sử dụng tùy chọn này, hộp thoại sẽ cố gắng mở lại thiết bị đầu cuối để nó có thể ghi vào màn hình. Tùy thuộc vào nền tảng và môi trường của bạn, điều đó có thể thất bại.

Bất cứ ai cũng có thể nói trong nền tảng hoặc môi trường mà nó không hoạt động? Liệu chuyển hướng dialogđầu ra để 2>&1 >/dev/ttythay vào đó làm việc tốt hơn?


4

Trong trường hợp ai đó đã hạ cánh ở đây từ Google và mặc dù câu hỏi này yêu cầu cụ thể về bash, đây là một cách khác:

Bạn có thể sử dụng zenity . Zenity là một tiện ích đồ họa có thể được sử dụng bên trong các tập lệnh bash. Nhưng tất nhiên điều này sẽ yêu cầu một máy chủ X như user877329 đã chỉ ra một cách chính xác.

sudo apt-get install zenity

Sau đó, trong kịch bản của bạn:

RETVAL=`zenity --entry --title="Hi" --text="What is your username"`

Liên kết hữu ích .


3
Trừ khi không có máy chủ X
user877329

1
OP muốn biết về dialog. Giống như tôi đến và hỏi bạn "Làm thế nào để tôi viết cái này và cái kia bằng con trăn?", Nhưng bạn cho tôi bash - tôi rất vui vì điều này có thể được thực hiện theo cách khác, nhưng đó không phải là điều tôi đang hỏi
Sergiy Kolodyazhnyy

@ Nhận xét của bạn không hợp lệ, câu trả lời của tôi là không: Tiện ích cung cấp một giải pháp thay thế hoàn toàn hợp lệ và đơn giản cho giải pháp mà OP yêu cầu.
Wtower

3

Câu trả lời được cung cấp bởi Sneetsher có phần thanh lịch hơn, nhưng tôi có thể giải thích điều gì sai: Giá trị của $$nó là khác nhau bên trong backticks (bởi vì nó bắt đầu một lớp vỏ mới và $$là PID của lớp vỏ hiện tại). Bạn sẽ muốn đặt tên tệp trong một biến, sau đó tham khảo biến đó trong suốt.

#!/bin/bash
t=$(mktemp -t inputbox.XXXXXXXXX) || exit
trap 'rm -f "$t"' EXIT         # remove temp file when done
trap 'exit 127' HUP STOP TERM  # remove if interrupted, too
dialog --inputbox \
    "What is your username?" 0 0 2>"$t"
retval=$?
input=$(cat "$t")  # Prefer $(...) over `...`
case $retval in
  0)    echo "Your username is '$input'";;
  1)    echo "Cancel pressed.";;
esac

Trong trường hợp này, tránh tệp tạm thời sẽ là một giải pháp tốt hơn, nhưng sẽ có nhiều tình huống mà bạn không thể tránh được tệp tạm thời.

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.