Tại sao tôi cần phải đặt ra những người làm thế giới trong cùng một dòng với người khác


28

1. Tóm tắt

Tôi không hiểu, tại sao tôi cần quy tắc bashate E010 .


2. Chi tiết

Tôi sử dụng bashate cho .shcác tập tin linting . Quy tắc E010:

làm không trên cùng một dòng như cho

for bashate:

  • Chính xác:

    #!/bin/bash
    for f in bash/*.sh; do
        sashacommand "$f"
    done
  • Lỗi:

    #!/bin/bash
    for f in bash/*.sh
        do sashacommand "$f"
    done

Có bất kỳ đối số hợp lệ, tại sao tôi cần fordotrong cùng một dòng?


3. Không hữu ích

Tôi không thể tìm thấy câu trả lời cho câu hỏi của mình trong:

  1. Google
  2. Các bài viết về thực hành mã hóa tốt nhất ( ví dụ )
  3. tài liệu bashate . Tôi chỉ tìm thấy:

    Một bộ quy tắc giúp giữ mọi thứ nhất quán trong các khối điều khiển. Những thứ này bị bỏ qua trên những hàng dài có phần tiếp nối, bởi vì việc không kiểm soát đó là một loại thú vị


3
Việc thụt lề dochắc chắn là một chút khác thường, nhưng for ... \ndo\n<indent>body...cực kỳ phổ biến và tôi thậm chí còn ước tính nhiều hơn thế for ... ; do. Nó cũng phàn nàn về điều đó?
Michael Homer

20
bashatelà một người kiểm tra phong cách . Phong cách vốn có chủ quan. Đừng sử dụng nó nếu bạn không thích kiểu thư viện nghệ thuật mà nó áp đặt. Thay vào đó, bạn nên xem xét một cú pháp / trình kiểm tra lỗi như shellcheck .
meuh

@meuh, cảm ơn, tôi đã sử dụng ShellCheck. câu hỏi của tôi: E010- chỉ phong cách cai trị hoặc trong một số trường hợp tôi cần cholàm trong cùng một dòng không chỉ bởi lý do phong cách.
Саша Черных

10
Không bao giờ có một nghĩa vụ cú pháp có cholàm trên cùng một dòng trong vỏ.
meuh

1
@ Саша Черных Bản thân nó không phải là vết lõm mà không bình thường, đó là sự thụt vào do. Nó giống như thụt lề mở của một ifvà thêm mã trên cùng một dòng trong một ngôn ngữ như C. Một ví dụ khác, nếu python cho phép, sẽ đặt :một dấu ifthụt vào dòng tiếp theo và thêm mã vào cùng dòng đó. Nó sẽ làm cho nó khác biệt với các dòng bổ sung trong cơ thể.
JoL

Câu trả lời:


60

Cú pháp, hai đoạn mã sau đây là chính xác và tương đương:

for f in bash/*.sh; do
    sashacommand "$f"
done
for f in bash/*.sh
    do sashacommand "$f"
done

Cái thứ hai có thể có thể được cho là khó đọc hơn vì dohơi làm xáo trộn lệnh trong phần thân của vòng lặp. Nếu vòng lặp chứa nhiều lệnh và lệnh tiếp theo nằm trên một dòng mới, phần obfuscation sẽ được tô sáng thêm:

for f in *
    do cmd1
    cmd2
done

... nhưng để đánh dấu nó là "lỗi" là ý kiến ​​cá nhân của ai đó chứ không phải là sự thật khách quan.

Nói chung, hầu như bất kỳ ;có thể được thay thế bởi một dòng mới. Cả hai ;và dòng mới là dấu chấm hết lệnh. dolà một từ khóa có nghĩa là "ở đây làm theo những gì cần phải làm (trong forvòng lặp này )".

for f in *; do ...; done

giống như

for f in *
do
   ...
done

và như

for f in *; do
   ...
done

Lý do để sử dụng cái này hơn cái khác là khả năng đọc và các quy ước kiểu địa phương / cá nhân.


Ý kiến ​​cá nhân:

Trong các tiêu đề vòng lặp rất dài , tôi nghĩ rằng có thể có ý nghĩa khi đặt domột dòng mới, như trong

for i in animals people houses thoughts basketballs bees
do
    ...
done

hoặc là

for i in        \
    animals     \
    people      \
    houses      \
    thoughts    \
    basketballs \
    bees
do
    ...
done

Điều tương tự cũng xảy ra thentrong một iftuyên bố.

Nhưng một lần nữa, điều này tùy thuộc vào sở thích phong cách cá nhân của một người, hoặc cho bất kỳ nhóm / dự án phong cách mã hóa nào đang sử dụng.


Bạn nói rằng các tiêu đề trong vòng lặp rất dài, có thể có ý nghĩa khi thực hiện trên một dòng mới. Bạn có thể cung cấp một lý do cho điều đó? Cho rằng tiêu đề phải được theo sau do, tôi không thấy lý do tại sao đặt nó trên dòng tiếp theo sẽ giúp dễ đọc.
Konrad Rudolph

3
@KonradRudolph Thiết bị đầu cuối của tôi rộng 80 ký tự. Nếu danh sách kết thúc tốt đẹp, tôi sẽ biến nó thành một tập hợp các dòng tiếp tục (như trong ví dụ cuối cùng của tôi), nếu nó gần như kết thúc, tôi sẽ tự đặt do(hoặc then) trên một dòng (như trong ví dụ thứ hai đến ví dụ cuối cùng). Tất cả điều này phải de với sở thích cá nhân. Tôi không thích các dòng quá dài, một phần vì thiết bị đầu cuối của tôi "chỉ" rộng 80 ký tự và một phần vì tôi nghĩ nó trông không gọn gàng. Tôi cũng thấy khó phân tích các dòng rất dài cho các lỗi.
Kusalananda

1
Có vẻ như không cần thiết để tiếp tục chỉ ra rằng đây là ý kiến. bashate là một hướng dẫn phong cách, do đó, nó vốn dựa trên ý kiến.
Barmar

4
@Barmar, xin lưu ý rằng câu hỏi ở đây sử dụng cụm từ như "cần" và "quy tắc", và các lệnh gọi bashate readme có domột dòng riêng biệt là "lỗi". Đó là những cụm từ khá nghiêm ngặt, vì vậy vẻ đáng để chỉ ra rằng, hoàn toàn ngược lại, cái gọi là "quy tắc" thực sự chỉ là một ý kiến ​​chủ quan.
ilkkachu

2
@mtraceur Phải, tôi không đặt câu hỏi về sở thích cá nhân. Nhưng hãy lưu ý rằng giới hạn cột dễ đọc mà bạn trích dẫn không áp dụng cho mã. Nó chỉ áp dụng cho văn xuôi. Chuyển động của mắt về cơ bản là khác nhau đối với việc đọc mã, vì vậy bằng chứng từ những nghiên cứu này không được áp dụng ở đây. Và đối với việc sử dụng các lý do lịch sử không còn áp dụng như lý do hợp lý, chúng tôi cũng đã sử dụng tên tệp 8.3 trước đây.
Konrad Rudolph

28

Lưu ý những gì nó nói trên đầu trang:

bashate: Tương đương pep8 cho các tập lệnh bash

PEP8 là Hướng dẫn về Phong cách cho Mã Python. Mặc dù người Python thường rất coi trọng vấn đề phong cách của họ [cần dẫn nguồn] , nhưng đó chỉ là hướng dẫn. Chúng tôi có thể đưa ra những mặt tích cực cho cả hai việc đặt docùng một dòng với forvà đặt nó trên một dòng của riêng mình.

Đó là cuộc thảo luận tương tự như nơi đặt {mã C khi bắt đầu một ifhoặc whilechặn (hoặc như vậy).


Một vài dòng dưới đây trong tài liệu, có một quy tắc thú vị khác:

E020: Khai báo hàm không ở định dạng ^function name {$

Tôi giả sử vấn đề ở đây là tác giả của hướng dẫn phong cách đó nghĩ rằng việc sử dụng functiontừ khóa là cần thiết để người đọc nhận ra một khai báo hàm. Tuy nhiên, function foolà một cách không chuẩn để xác định hàm: cách chuẩn là foo(). Sự khác biệt duy nhất giữa hai (trong Bash) là cái kia khó chuyển sang hệ vỏ tiêu chuẩn, như /bin/shtrong Debian hoặc Ubuntu.

Vì vậy, tôi sẽ đề nghị dùng bất kỳ và tất cả các hướng dẫn phong cách như vậy với một hạt muối hoặc ba, và tự quyết định phong cách tốt nhất là gì. Trình kiểm tra kiểu tốt cho phép vô hiệu hóa một số kiểm tra (bashate bashate -i E010,E011phải bỏ qua hai kiểm tra đó.) Trình kiểm tra kiểu tuyệt vời sẽ cho phép bạn sửa đổi các kiểm tra, ví dụ: để kiểm tra ngược lại với E020, tại đây.


12

TL; DR: Bạn không cần. Đó chỉ là ý kiến ​​của một số anh chàng.

Giống như nhiều người khác, tôi đã viết forcác vòng lặp như thế này trong nhiều thập kỷ:

for F in arg1 arg2 arg*
do
    somecommand "$F"
done

Bố cục này nêu bật thực tế là do ... donebao quanh thân vòng lặp, giống như dấu ngoặc nhọn trong các ngôn ngữ giống như C và cho phép các dòng mới tách các thành phần của cấu trúc vòng lặp.

Tất nhiên, cũng có những cuộc chiến tôn giáo về nơi đặt niềng răng xoăn, vì vậy bạn có thể nói rằng bồi thẩm đoàn vẫn chưa kết thúc. IMHO, đây rõ ràng là cách nó được thiết kế để hoạt động; Bourne thích các dấu phân cách trùng khớp, xem if ... fi, case ... esacvà nhu cầu về dấu chấm phẩy trong phiên bản ngắn hơn cho thấy rằng bạn đang làm cho nó ngắn hơn thiết kế ban đầu. Không có gì sai với điều đó; tiến bộ công nghệ và rất nhiều thứ mà trước đây dường như là một ý tưởng hay giờ lại được tán thành goto. Nhưng cho đến khi toàn bộ cộng đồng kịch bản shell chấp nhận sở thích của bashatetác giả, bạn không phải làm gì cả.


3
Cái fitương ứng với if, esacv.v. đến từ Algol 68. Lý do duy nhất của một forvòng lặp dokhông kết thúc odlà đó odlà tên của một tiện ích tiêu chuẩn hiện có. Xem en.wikipedia.org/wiki/ALGOL_68C#Algol_68C_and_Unix
Kusalananda

1
Các khối được phân tách bằng từ phải và cũng được sử dụng trong các ngôn ngữ khác của họ Algol, bao gồm cả Pascal (sử dụng, begin ... endv.v.).
alexis

2
Chưa từng nghe câu chuyện về odđiều đó, thật buồn cười ... (Mặc dù, tại sao không kết thúc vòng lặp với rof, sau đó?)
alexis

2
@alexis Vâng, như Kusalananda đã nói, nó đến từ Algol 68, đó là điểm mấu chốt. Stephen Bourne, người tạo ra vỏ Bourne ban đầu, bị ảnh hưởng nặng nề bởi ngôn ngữ đó, và đó là lý do tại sao anh ta mắc kẹt với cú pháp đó. Ngay cả khi anh ấy đang viết bằng C. Xem mã nguồn cho bourne shell: minnie.tuhs.org//cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/mac.h Oh, và bởi cách, BEGINENDđược định nghĩa là tốt.
Sergiy Kolodyazhnyy

1
Toàn bộ phong cách định dạng này cũng đến từ Algol 68. Của nó FORDOcũng sẽ là trên dòng riêng biệt, theo quy ước, trừ khi toàn bộ vòng lặp sẽ dễ dàng phù hợp trên một dòng đơn.
rebierpost

3

Tôi ngạc nhiên không ai đã đề cập đến cú pháp di động hợp lệ này:

set alfa bravo charlie
for q do
  echo "$q"
done

Lưu ý cẩn thận rằng fordotrên cùng một dòng, không có dấu chấm phẩy. Kết quả:

alfa
bravo
charlie

Tôi chấp nhận câu trả lời này cho việc cắm một đề cập về cú pháp tối nghĩa này (nhưng rất quan trọng đối với mã shell sạch và di động trong một số trường hợp), tuy nhiên, đáng để giải thích rõ ràng với mọi người rằng điều này làm tắc nghẽn các tham số vị trí, và tôi cũng cảm thấy buộc phải đề cập đến điều đó chỉ "thực sự di động (tm)" hình thức là một trong những nơi for qdođang trên đường riêng biệt (hình thức trong ví dụ này là không được hỗ trợ một vài thập kỷ trước đây trên bản gốc Almquish vỏ ( ash): in-ulm.de/~mascheck/various/ bourne_args / # endnote )
mtraceur

Mặc dù ví dụ trong câu trả lời này có hiệu quả với tôi, nhưng việc áp dụng nó vào ví dụ trong câu hỏi của OP không hoạt động.
Scribpetacher

3

Một số câu trả lời tốt ở đây. Luôn luôn hướng dẫn phong cách với một hạt muối, và IMHO và trải nghiệm, luôn luôn quan tâm đến mức độ vừa phải đối với bất kỳ cộng đồng nào đầy rẫy những giáo điều quá mức khi nói đến phong cách. Gần giống như họ tin rằng khi họ HOÀN TOÀN nhận được lần cuối cùng tôi chấm, và lần cuối cùng T vượt qua, thì phần mềm sẽ hoạt động. Đôi khi, cần nhiều hơn phong cách hoàn hảo để loại bỏ lỗi ...

Khi tôi bắt đầu học shell, hầu hết các tập lệnh và thao tác ngoài đó đều sử dụng định dạng dấu chấm phẩy nội tuyến

for i in "$@"; do
    stuff
done

nhưng vì tôi thiếu kinh nghiệm, tôi có một chút khó khăn khi phát hiện ra; và làm - cả hai điều cần thiết để xác nhận tính chính xác cú pháp. Vì vậy, tôi thích làm tất cả trên dòng tiếp theo của chính nó. Tôi không còn làm điều đó nữa (ý định chơi chữ)

Hơn nữa, lệnh 'while' là một ứng cử viên tuyệt vời cho một mẹo nhỏ hay:

while prep1; prep2; condition; do
    stuff
done

nhưng khi các lệnh chuẩn bị hơi cồng kềnh và / hoặc điều kiện phức tạp, nó được định dạng tốt hơn là

while
    prep1
    prep2
    condition
do
    stuff
done

và sau đó nối thêm việc làm như "; do" được tích cực hóa.

Bạn thậm chí có thể trở nên dữ dội hơn thế:

while
    if con1; then
      cond2
    elif cond3; then
      cond4
    elif cond5; then
      cond6
    else
      cond7
    fi
do
    stuff
done

bởi vì mỗi câu là một biểu thức Lưu ý cách cả hai phong cách được sử dụng cơ hội. Giữ nó sạch sẽ và nó khá dễ đọc. Nhỏ gọn hoặc chế tạo nó theo tên của phong cách hoặc "tiết kiệm không gian" và nó trở thành một mớ hỗn độn khủng khiếp.

Vì thế! Với phong cách khá baroque của các kịch bản shell nói chung, bất cứ điều gì nhằm tăng độ rõ ràng và dễ dàng truy cập trực quan đến các biểu tượng quan trọng luôn là một điều tốt.

Biểu mẫu trong đó 'do' được viết nội tuyến với lệnh thật ngọt ngào khi bạn có một lệnh nhỏ - Tôi không tìm thấy 'làm' bị ẩn một cách trực quan, cũng không phải là lệnh bên trong thực sự bị che khuất:

for i in whatever
  do stuff
done

Tôi thấy rằng khá dễ chịu khi nhìn vào, và nó có điểm tương đồng với while, if và case:

while condition
  do stuff
end

if condition
  then stuff1
  else stuff2
fi

case $blah in
  a) stuff1;;
  b) stuff2;;
  c) stuff3;;
  *) stuffInfinity;;
esac

Rõ ràng và gọn gàng chung là tất cả những gì Codd * yêu cầu của bạn.

* Edgar F. Codd, cha đẻ của lý thuyết cơ sở dữ liệu quan hệ.


1
Chưa bao giờ thấy một whilevới một ifđiều kiện trước đây. Mát mẻ!
Joe
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.