:
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, :> file
là một thành ngữ khá phổ biến để cắt bớt các tệp. : >file
Mặ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ừ otherfile
mộ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 >file
sẽ hút ít hơn và tránh phải cắt bớt tệp trước. read -r
khô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: read
phả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 read
chỉ đị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ó split
có 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ì $5
trong 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 gensub
trê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 print
như trước đây, nhưng tail
thay 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à: > file
thay vào đó.