Cách dễ nhất để tìm trích dẫn bị thiếu trong bash một kịch bản?


7

Tôi có một tập lệnh bash hiện dài hơn 700 dòng. Sau một vòng chỉnh sửa đặc biệt dài, bây giờ lỗi như vậy:

./run_me.sh: line 693: unexpected EOF while looking for matching `''
./run_me.sh: line 702: syntax error: unexpected end of file

Tuy nhiên, không có gì sai tôi có thể thấy với dòng 693. Thậm chí không có trích dẫn nào về nó.

Tôi đã thử chạy bash -x run_me.shvà có thể thấy dòng cuối cùng chạy, nhưng dòng đó không có gì sai cả (và mã giữa dòng đó và 693, hầu hết là mã).

Tôi có thể nhận xét toàn bộ các đoạn mã, nhưng sau đó tôi có nhiều khả năng thấy lỗi do thiếu chức năng, v.v., thay vì lỗi EOF tôi đang gặp phải.

Vậy làm thế nào để một người nào đó tìm thấy trích dẫn bị thiếu, nếu số dòng được báo cáo không chính xác?

(Tại sao báo cáo số dòng của bash lại quá xa?)

Biên tập

Tình cờ, tôi đã tìm thấy lỗi cụ thể của mình (bằng cách bình luận swathes), thực sự là một thiếu sót }trong việc mở rộng biến ở một số dòng tùy ý không ở gần dòng được chỉ ra bởi thông báo lỗi - đánh dấu cú pháp dựa trên trích dẫn không giúp ích ở đây, ví dụ như với niềng răng bị thiếu trong "${MY_ARRAY[@]"(nên "${MY_ARRAY[@]}").


Bạn không cần phải bình luận swathes - chỉ phần đầu của mỗi lệnh ghép (hoặc định nghĩa hàm) . Sau đó bỏ ghi chú từng cái một bắt đầu từ phần đầu của tệp. Sau đó, chỉ cần làm sh -nv <scriptnhư bạn làm. Ngay sau khi thông báo lỗi của bạn thay đổi, bạn đã tìm thấy lệnh ghép trong đó vấn đề của bạn nằm ở đó. Và các số dòng là tốt - mỗi hàm có một số riêng.
mikeerv

@mikeerv - bạn có thể mở rộng trên 'số dòng có ổn không - mỗi hàm có giá trị riêng' ? Chắc chắn không có chức năng nào dài 693 dòng (trừ khi bạn tính chính tập lệnh là một hàm). Nếu lỗi không ở hoặc giữa hai dòng được báo cáo, điều đó có vẻ không ổn đối với tôi. Nếu có một số phương pháp để rút ra / thần thánh dòng thất bại thực tế (hoặc thậm chí bắt đầu lệnh ghép thất bại) từ các số dòng được báo cáo bởi bash, có thể đó sẽ là một khởi đầu tốt.
jimbobmcgee

Ok, bạn đã tạo ra những điểm tốt, nhưng nếu bạn đã thử -nvđiều đó, bạn có thể hiểu rõ hơn - các lời nhắc sẽ gợi ý cho bạn. Bạn sẽ nhận được $PS2khi vỏ có lúc bắt đầu diễn giải một trích dẫn hoặc lớp ghép và không được quản lý đóng mã thông báo đó kể từ khi dòng mới nhất xuất hiện trong đầu vào. Ngoài ra hãy thử: PS4='LAST EXECLINE: $((LAST+!(LAST=LINENO)))'; set -xbởi vì các lineno đôi khi có thể trở nên khá buồn cười trong các lớp con.
mikeerv

Trên thực tế, hóa ra, tôi đoán rằng tôi đã giải thích ít nhất một số điều đó tốt hơn một chút trước đây .
mikeerv 27/05/2015

Câu trả lời:


7

Một cách tiếp cận công nghệ thấp là

tr -cd "'\n" < run_me.sh | awk 'length%2==1 {print NR, $0}'

Các trxóa tất cả các nhân vật ngoại trừ dấu nháy đơn và dòng mới, và awkxác định các dòng có một số lẻ của các nhân vật (ví dụ, không phù hợp dấu ngoặc kép). Kiểm tra chúng riêng lẻ; lưu ý rằng các chuỗi hợp lệ như "That's not a bug!"sẽ được gắn cờ. Nếu điều này không làm nổi bật vấn đề, hãy thử lại với '"\n' (để tìm dấu ngoặc kép không khớp). Tiếp theo, mở rộng trđể cho phép (), {}và cuối cùng {} phải đi qua. Tại thời điểm này, kiểm tra thủ công đầu ra trở thành một sự theo đuổi ít hiệu quả hơn; trong khi ()thường được khớp trong cùng một dòng, và dấu ngoặc kép và dấu ngoặc vuông hầu như luôn luôn như vậy, điều này không đúng {}.

Nếu bạn đã thu hẹp vấn đề xuống không khớp với dấu ngoặc nhọn và đặc biệt nếu bạn đã thu hẹp phạm vi trong tệp, hãy chuyển đến Kế hoạch B. Mở tệp trong vim(hoặc vi). Đi đến một {ký tự mà bạn tin là trước lỗi và gõ %. Nếu con trỏ nhảy đến cái } mà bạn nghĩ phù hợp với cái {bạn đã bắt đầu, hãy chuyển sang tiếp theo {và lặp lại. Nếu nó nhảy đến }mức không khớp với {bạn đã bắt đầu, lỗi sẽ xảy ra giữa hai lần niềng răng đó. Nếu nó không di chuyển, lỗi xảy ra giữa vị trí hiện tại của bạn và phần cuối của tệp. Phóng to.

Cách tiếp cận này có thể phù hợp hơn một chút với các tệp chương trình bằng các ngôn ngữ như C, C ++ và Java (nếu trình biên dịch của chúng không thực hiện công việc đủ tốt), nhưng nó sẽ hoạt động khá tốt đối với các tập lệnh shell.


Cảm ơn! Đôi khi công nghệ thấp tốt hơn không công nghệ! đã thay đổi 'thành a \ "và tìm thấy trích dẫn kép bị thiếu của tôi sau vài giây.
mike

5

Cách dễ nhất? Sử dụng trình chỉnh sửa với màu cú pháp nhận biết vỏ bạn đang sử dụng và kiểm tra trực quan. Khi bạn nhận được một chuỗi lớn màu chuỗi, bạn biết bạn đã bỏ qua một trích dẫn. Chỉ cần bất kỳ trình soạn thảo lập trình phong nha có màu cú pháp.

Tô màu cú pháp đôi khi làm cho nó sai, nhưng đó thường là một dấu hiệu cho thấy chương trình của bạn quá phức tạp và con người cũng có thể hiểu sai.

Đối với lập trình shell, hãy chắc chắn để sử dụng một phông chữ nơi ", '`rất dễ để nói ngoài. Kiểm tra xem bạn đã vô tình sử dụng các ký tự không phải ASCII trông giống như các trích dẫn ASCII, chẳng hạn như ‘’“”.


EOF gợi ý một backquote bị thiếu. Trong trường hợp bash trích dẫn bị thiếu, báo cáo "chuỗi trích dẫn bị hủy".
Emmanuel

Thực sự là một mất tích }bên trong một chuỗi trích dẫn, mà màu sắc của Geany không phát hiện ra.
jimbobmcgee

@jimbobmcgee À. Emacs không phát hiện ra điều này, nhưng Vim thì có.
Gilles 'SO- ngừng trở thành ác quỷ'

Vâng vim, làm một công việc hợp lý ... cuối cùng. Đầu tiên phải ngăn chặn nó lờ đi :syntax onbằng cách cài đặt vim-enhancedqua vim-minimal(nhờ Fedora!), Sau đó đã phải buộc nó vào một bảng màu phong nha, vì màu xanh đậm thực sự là nhìn thấy được (nhờ LXTerminal!). Sau đó, vimđã làm nổi bật niềng răng bị thiếu với một nền đỏ đẹp!
jimbobmcgee

Đôi khi làm điều đó có thể khó khăn. Bây giờ tôi có một mảng với hơn 2000 giá trị, xuất hiện màu trắng trong Sublime Text, trong đó tất cả các mảng khác của tôi có màu vàng. Tôi sẽ phải chú ý và di chuyển sang một bên trong một thời gian rất dài.
DisplayName

5

Một công cụ linting bên ngoài như ShellCheck có thể phát hiện các vấn đề và có thể có thông điệp và vị trí tốt hơn bashchính nó.

Đối với một chương trình chủ yếu là các echocâu lệnh "${MY_ARRAY[1]"ở giữa, ShellCheck nói với bạn rằng nó không thể phân tích chuỗi được trích dẫn. Nó thậm chí còn khắc phục sự cố xuống $ký tự và gợi ý rằng việc mở rộng tham số có lỗi.

ShellCheck hoạt động với Vim, Emacs, SublimeText và Atom (trong số những người khác).


1

Tôi đã có thể giải quyết một vấn đề lớn mà tôi gặp phải trong tập lệnh bash 2000+ dòng bằng giải pháp công nghệ thấp từ G-Man.

Tôi chỉ cần thêm dòng sau đây tương tự với số lượng nhân đôi số lẻ so với câu trả lời của G-Man cho các câu đơn.

tr -cd "\"\n" < my_script.sh | awk 'length%2==1 {print NR, $0}'

Btw, shellcheck.net rất hay và mọi kịch bản hay đều phải trải qua.

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.