Lệnh Bash trong chuỗi đang thực thi khi tôi tạo chuỗi chứ không phải khi tôi sử dụng chuỗi sau


10

Tôi còn khá mới với shell scripting, nhưng gần như đã hoàn thành một script sử dụng chương trình lftp . Phần kịch bản tôi gặp sự cố là khi tôi tạo một chuỗi lệnh dài (cách nhau ;).

for var in something
do
    ...
    commands_to_run+="echo Result is `tail -n 1 $somefile`;"
done

Điều tôi nhận thấy là tailchương trình - được gói trong backticks - đang được chạy khi vòng lặp for đang lặp, nhưng không phải khi tôi gọi chuỗi lệnh sau trong tập lệnh của mình.

Thật không may, nội dung của $ somefile không ở giai đoạn này đã sẵn sàng để được kiểm tra. Làm cách nào tôi có thể thực hiện lệnh để thực thi khi tôi cần chứ không phải trong khi tôi đang tạo chuỗi?

Câu trả lời:


8

Điều này là một chút khó khăn. Thông tin mà Hauke ​​đã cung cấp là chính xác, đó chỉ là vấn đề phân tích nó cho trường hợp sử dụng của bạn.

Cách dễ nhất là sử dụng $()cú pháp trong khi thoát khỏi $định nghĩa sao cho định nghĩa biến không thực thi lệnh được bao quanh bởi $()tại thời điểm định nghĩa. Thông báo trước là kết quả cuối cùng phải được đánh giá lại (thông qua eval) bởi trình bao tại thời điểm thực hiện thực tế để lệnh lồng nhau thực thi.

Việc xem xét một ví dụ dễ dàng hơn nhiều, vì vậy hãy lấy ví dụ này, điều này sẽ đưa bạn đi đúng hướng:

for((i=0;i<10;i++)); do 
  date +%s.%N  # Print a timestamp (in format seconds.nanoseconds)
  test="echo \$(date +%s.%N)" # Save a command to do the same
  sleep 1      # Sleep for a second
  eval "$test" # Evaluate the command saved in variable 'test'
  echo         # Print a new line before the next iteration
done

Đây là đầu ra mẫu từ ví dụ trên (được cắt thành một lần lặp):

1398832186.133661344
1398832187.139076728

Bạn sẽ nhận thấy rằng dấu thời gian thứ hai cho mỗi vòng lặp là khoảng một giây sau lần đầu tiên. Ngược lại, nếu bạn thực hiện các thử nghiệm tương tự mà không cần thoát khỏi $trong testđịnh nghĩa và loại bỏ eval, hai timestamps sẽ gần khớp với nhau.

Đừng có thói quen sử dụng evaltrong hầu hết các tình huống, nhưng đây là một trong những cách mà tôi không biết cách tốt để tránh nó. Hy vọng điều này sẽ giúp. Chúc may mắn!


Cảm ơn rất nhiều, tôi đã thử sử dụng $(...)như Hauke ​​đề xuất nhưng dấu gạch chéo ngược là chìa khóa.
Ricky

Mặc dù vậy, rất vui vì nó đã giúp - hãy nhớ rằng, chìa khóa ở đây thực sự là evalvì bạn có thể làm điều tương tự bằng cách không thoát $và sử dụng dấu ngoặc đơn ( ') thay vì dấu ngoặc kép ( ") để bao quanh lệnh của bạn.
daBeamer

Bây giờ tôi mới nhận ra, giống như với các đề xuất của Huake, một khi tôi thử sử dụng điều này trong chương trình lftp, tiếng vang chỉ đơn giản là in lệnh, nó sẽ không thực sự chạy nó. Có thể phải thử danh sách gửi thư của họ để được giúp đỡ cụ thể hơn.
Ricky

Lệnh nào mà bạn đang cố thực hiện? Tôi có ấn tượng rằng bạn muốn echomột chuỗi có nội dung bao gồm đầu ra của một lệnh lồng nhau thực thi bị trì hoãn.
daBeamer

1
@Ricky Tôi sẽ phải đồng ý với tất cả các điểm từ @HaukeLaging. Mã như là trừ đi echosẽ không hoạt động vì không có lệnh nào eval, mà là một chuỗi. Nếu bạn có một ví dụ thích hợp hơn cho chúng tôi, chúng tôi có thể cố gắng giúp đỡ.
daBeamer

6

Có một số cấp độ trích dẫn. Dấu ngoặc kép ( "...") khoảng trắng bảo vệ và một số ký tự đặc biệt ( ~, &, |, ;, ...) nhưng không ngăn cản sự bành trướng tham số và thay thế lệnh.

Bạn cần một dấu ngoặc đơn ( ') hoặc dấu gạch chéo ngược trước các ký tự "nguy hiểm".

Nói chung: Bạn nên xem xét sử dụng $(tail ...)thay vì backticks. Backticks là tiêu chuẩn cũ hơn nhưng chúng ta đang nói về quá cũ mà $()không gây ra vấn đề cho hầu hết mọi người. Phiên bản mới dễ đọc hơn và có thể được lồng vào nhau. Hãy để một mình các vấn đề định dạng ở đây trên sx ...


Cảm ơn đã trả lời nhanh Hauke. Thật không may, thay thế backticks bằng khuyến nghị $(...)vẫn tạo ra kết quả tương tự - shell thực thi điều này khi chuỗi của tôi được xác định.
Ricky

@Ricky Đó không phải là đề xuất thay thế. Bạn sẽ sử dụng $()nhưng bạn cần báo giá duy nhất nào.
Hauke ​​Laging

Vì vậy, không có sự kết hợp của những nhân vật sẽ đạt được những gì tôi sau?
Ricky

@Ricky Điều gì quá khó hiểu về "Bạn cần một dấu ngoặc đơn"? Bạn rõ ràng thậm chí không thử.
Hauke ​​Laging

Trên thực tế tôi đã làm, nhưng khi tôi sử dụng dấu ngoặc đơn, echo sẽ chỉ in mọi thứ trên dòng đó như một chuỗi bình thường. Điều gì là khó khăn về việc có thể cung cấp một ví dụ?
Ricky
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.