:là một tên khác cho true. Cả hai đều được tích hợp sẵn trong bash, nhưng không /bin/:, chỉ có một /bin/true. Chuyển hướng đầu ra gây ra shell cho open(2)tập tin với O_CREAT|O_TRUNC. Nếu không có gì được viết, nó vẫn ở độ dài bằng không.
Đặt hai mảnh đó lại với nhau, :> filelà một thành ngữ khá phổ biến để cắt bớt các tệp. : >fileMặc dù vậy, hầu hết mọi người sẽ cố gắng làm cho nó trông bớt kỳ lạ hơn bằng cách viết .
Vì bạn đã hỏi trong một nhận xét về dòng thứ 2, tôi sẽ biến nhận xét của mình thành câu trả lời. (mặc dù bạn không hỏi điều này trong câu hỏi của bạn.)
Dòng thứ 2 là một vòng lặp đọc các dòng từ otherfilemột số biến được đặt tên. Phần thân vòng lặp sử dụng echođể in chúng bằng các ;dấu phân cách thay vì bất kỳ khoảng trắng nào trước đây chúng có. fileđược đóng và mở lại (để nối thêm) mỗi lần lặp, bởi vì chuyển hướng nằm trong vòng lặp. Sử dụng while ...;do read -r ...;done <otherfile >filesẽ hút ít hơn và tránh phải cắt bớt tệp trước. read -rkhông ăn \như một nhân vật thoát.
Xử lý văn bản trong bash khá chậm. Một phần của điều đó là không thể tránh khỏi: readphải thực hiện một byte mỗi lần (một read(2)cuộc gọi hệ thống trên mỗi byte) để tránh làm quá mức ở cuối dòng. Sẽ tốt hơn nếu sử dụng đúng công cụ cho công việc:
awk -vOFS=';' '{ print $1, $2, $4, $5, $3 }' -- otherfile >file
--có nghĩa là kịch bản của bạn không bị hỏng nếu otherfileđược đặt tên như một cái gì đó ngớ ngẩn --version.
Đặt Dấu tách trường đầu ra thành ;nghĩa là bạn chỉ có thể chuyển nhiều trường dưới dạng đối số để in. Shell readchỉ định toàn bộ phần còn lại của dòng có khoảng trắng cho biến cuối cùng, nhưng không có cách nào để nói awk chỉ tách thành 5. Nếu điều đó quan trọng, có thể chỉ cần tiếp tục sử dụng vòng lặp bash, vì nó bất tiện trong awk. Perl làm cho điều này trở nên dễ dàng, vì nó splitcó thể lấy một trường tối đa, nhưng khởi động chậm hơn rất nhiều so với awk.
Trên thực tế, hóa ra nó không khó lắm, chỉ là một regex xấu xí để viết. Để có được phần còn lại thay vì $5trong awk, việc lặp qua các trường vẫn mất khoảng trắng ban đầu của chúng. Ý tưởng khả thi đầu tiên của tôi là sử dụng gensubtrên $0(toàn bộ dòng) để xóa 4 trường đầu tiên (nghĩa là không phải không gian theo sau là khoảng trắng), để lại mọi thứ khác:
awk -vOFS=';' '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1); print $1, $2, $4, tail, $3 }' -- otherfile >file
Tôi đã hiểu đúng ngay từ lần thử đầu tiên, nhưng thực tế là tôi rất ấn tượng với bản thân vì điều đó nói lên điều gì đó về tính dễ đọc của mã awk đó. >. <
Lưu ý cách nó giống printnhư trước đây, nhưng tailthay cho $5.
echo 'A B c DD e f g f' |
awk -vOFS=\; '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1);
print $1, $2, $4, tail, $3 }'
A;B;DD;e f g f;c
Điều này sẽ ấn tượng hơn nếu tôi có thể sao chép / dán nghĩa đen và cho thấy rằng nó đã đi qua trong đầu ra. Nhập một trong bash với ^ Q. ctrl-Q có nghĩa là Trích dẫn phím nhấn tiếp theo dưới dạng ký tự chữ, vì chỉnh sửa dòng kiểu emacs của bash giống như các biểu tượng thực tế cho việc này.
http://mywiki.wooledge.org/BashFAQ có một số nội dung hữu ích về cách viết kịch bản theo những cách sẽ không phá vỡ bất kể dữ liệu hoặc tên tệp nào bạn ném vào tập lệnh.
:>không phải là một toán tử duy nhất. Nó có thể dễ hiểu hơn nếu bạn đọc nó như là: > filethay vào đó.