Làm thế nào để ngắt một chuỗi dài thành nhiều dòng trong dấu nhắc đọc -p trong mã nguồn?


18

Tôi đang viết một kịch bản cài đặt sẽ được chạy như /bin/sh.

Có một dòng nhắc cho một tập tin:

read -p "goat can try change directory if cd fails to do so. Would you like to add this feature? [Y|n] " REPLY

Tôi muốn chia dòng dài này thành nhiều dòng để không có dòng nào vượt quá 80 ký tự. Tôi đang nói về các dòng trong mã nguồn của tập lệnh; không phải về các dòng sẽ được in trên màn hình khi tập lệnh được thực thi!

Những gì tôi đã thử:

  • Cách tiếp cận Frist:

    read -p "goat can try change directory if cd fails to do so. " \
        "Would you like to add this feature? [Y|n] " REPLY
    

    Điều này không hoạt động vì nó không in Would you like to add this feature? [Y|n].

  • Cách tiếp cận thứ hai:

    echo "goat can try change directory if cd fails to do so. " \
        "Would you like to add this feature? [Y|n] "
    read REPLY
    

    Không hoạt động tốt. Nó in một dòng mới sau lời nhắc. Thêm -ntùy chọn để echokhông trợ giúp: nó chỉ in:

    -n goat can try change directory if cd fails to do so. Would you like to add this feature? [Y|n]
    # empty line here
    
  • Cách giải quyết hiện tại của tôi là

    printf '%s %s ' \
        "goat can try change directory if cd fails to do so." \
        "Would you like to add this feature? [Y|n] "
    read REPLY
    

và tôi tự hỏi nếu có một cách tốt hơn.

Hãy nhớ rằng tôi đang tìm kiếm một /bin/shgiải pháp tương thích.


1
Tôi đề nghị bạn 1. sử dụng thiết bị đầu cuối và / hoặc cửa sổ soạn thảo rộng hơn (ví dụ: tôi sử dụng cột 192 theo thiết bị đầu cuối 51 dòng trên màn hình 1440p của mình - tuyệt vời để điều chỉnh các tệp nhật ký và chỉnh sửa mã nguồn trong vim) và 2. học cách chấp nhận thực tế là đôi khi các dòng mã nguồn sẽ dài hơn 80 ký tự - đó là điều không thể tránh khỏi. Nếu tôi sử dụng một phông chữ nhỏ hơn, tôi có thể có một thiết bị đầu cuối thậm chí rộng hơn nhưng thiết lập hiện tại của tôi là một sự thỏa hiệp tốt giữa chiều rộng và mức độ dễ đọc.
cas

Câu trả lời:


16

Trước hết, hãy tách rời việc đọc từ dòng văn bản bằng cách sử dụng một biến:

text="line-1 line-2"             ### Just an example.
read -p "$text" REPLY

Theo cách này, vấn đề trở thành: Làm thế nào để gán hai dòng cho một biến.

Tất nhiên, một nỗ lực đầu tiên để làm điều đó, là:

a="line-1 \
line-2"

Viết như vậy, var athực sự nhận được giá trị line-1 line-2.

Nhưng bạn không thích sự thụt lề mà điều này tạo ra, sau đó, chúng tôi có thể cố gắng đọc các dòng vào var từ một tài liệu ở đây (lưu ý rằng các dòng thụt vào bên trong tài liệu ở đây cần một tab, không phải khoảng trắng, để hoạt động chính xác):

    a="$(cat <<-_set_a_variable_
        line-1
        line-2
        _set_a_variable_
    )"
echo "test1 <$a>"

Nhưng điều đó sẽ thất bại khi thực sự hai dòng được viết $a. Một cách giải quyết để chỉ có một dòng có thể là:

    a="$( echo $(cat <<-_set_a_variable_
        line 1
        line 2
        _set_a_variable_
        ) )"
echo "test2 <$a>"

Đó là gần, nhưng tạo ra các vấn đề bổ sung khác.

Giải pháp đúng.

Tất cả những nỗ lực ở trên sẽ chỉ làm cho vấn đề này trở nên phức tạp hơn.

Một cách tiếp cận rất cơ bản và đơn giản là:

a="line-1"
a="$a line-2"
read -p "$a" REPLY

Mã cho ví dụ cụ thể của bạn là (đối với mọi shell có readhỗ trợ -p):

#!/bin/dash
    a="goat can try change directory if cd fails to do so."
    a="$a Would you like to add this feature? [Y|n] "
# absolute freedom to indent as you see fit.
        read -p "$a" REPLY

Đối với tất cả các shell khác, sử dụng:

#!/bin/dash
    a="goat can try change directory if cd fails to do so."
    a="$a Would you like to add this feature? [Y|n] "
# absolute freedom to indent as you see fit.
        printf '%s' "$a"; read REPLY

@BinaryZebra tôi biết. Tôi chỉ sửa lỗi "cho bất kỳ shell nào" vì không phải tất cả các shell đều đã đọc và không phải tất cả các shell đều có -p.
terdon

@terdon Cả hai chúng tôi đều đồng ý Đó là lý do cho lời cảm ơn :-). Cảm ơn một lần nữa.

1

Dấu gạch chéo ngược ở cuối các dòng đang cho phép tiếp tục lệnh trên nhiều dòng, không phải ngắt dòng thực tế trong đầu ra.

Vì vậy, cách tiếp cận đầu tiên của bạn, ví dụ, trở thành lệnh

read -p "goat can try change directory if cd fails to do so. " "Would you like to add this feature? [Y|n] " REPLY

Tôi không chắc tại sao bạn muốn đọc để xuất nhiều dòng, nhưng tôi chỉ đơn giản sẽ sử dụng readcho dòng nhắc và echo(các) dòng trước.

Để làm cho mã dễ đọc hơn trên nhiều dòng, đừng đóng / mở dấu ngoặc kép giữa các dòng.

Thử đi:

read -p "goat can try change directory if cd fails to do so. \
Would you like to add this feature? [Y|n] " REPLY

Tôi không muốn nó in hai dòng! Tôi chỉ muốn mã phù hợp với 80 ký tự trên mỗi dòng trong mã nguồn của tập lệnh ! Cảm ơn bạn đã trả lời mặc dù :)
Mateusz Piotrowski

Tôi không thích cách tiếp cận mà bạn đề xuất vì không có vết lõm. Nếu tôi readbị thụt vào trong một hàm thì cách tiếp cận của bạn dường như làm rối loạn khả năng đọc.
Mateusz Piotrowski

1

Tôi thấy cách tiếp cận của @ BinaryZebra sử dụng một biến để sạch hơn, nhưng bạn cũng có thể thực hiện theo cách bạn đang cố gắng. Bạn chỉ cần giữ các ngắt dòng bên trong dấu ngoặc kép:

read -p "goat can try change directory if cd fails to do so. \
Would you like to add this feature? [Y|n] " REPLY

Bạn có nghĩ rằng việc thêm dòng mới sau mỗi dòng sẽ tăng khả năng đọc? Bởi vì tôi đã không tìm cách chèn \nvào lời nhắc của mình. Tôi chỉ muốn chia thành nhiều dòng để mỗi dòng dài tối đa 80 ký tự.
Mateusz Piotrowski

1
@MateuszPiotrowski oh, điều đó có ý nghĩa hơn nhiều. Sau đó, câu trả lời của tôi không hữu ích lắm. Vui lòng chỉnh sửa câu hỏi của bạn và làm rõ rằng bạn muốn tách mã chứ không phải đầu ra. Bây giờ tôi đang sử dụng điện thoại di động nhưng tôi sẽ xem liệu tôi có thể nghĩ ra thứ gì vào ngày mai không.
terdon

1
@MateuszPiotrowski đã hoàn thành, tôi đã thêm một phiên bản hoạt động của những gì bạn đang cố gắng ban đầu.
terdon

0

Còn cái này thì sao:

#! / bin / bash
đọc -p "Xin chào
thế giới
đây là một
đa dòng
nhắc nhở: "KHUYẾN MÃI
echo $ KHUYẾN MÃI


Làm thế nào để bạn thụt lề nó?
Mateusz Piotrowski
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.