Tôi có thể thực hiện `cut` thay đổi một tập tin tại chỗ không?


Câu trả lời:


14

Bạn không thể. Hoặc sử dụng ed hoặc GNU sed hoặc perl, hoặc làm những gì họ làm đằng sau hậu trường, đó là tạo một tệp mới cho nội dung.

ed, xách tay:

ed foo <<EOF
1,$s/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/
w
q
EOF

GNU sed:

sed -i -e 's/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/' foo

Perl:

perl -i -l -F, -pae 'print @F[1,3]' foo

cut, tạo một tệp mới (được khuyến nghị, vì nếu tập lệnh của bạn bị gián đoạn, bạn có thể chạy lại nó):

cut -d , -f 1,3 <foo >foo.new &&
mv -f foo.new foo

cut, thay thế tệp tại chỗ (giữ quyền sở hữu và quyền của foo, nhưng cần bảo vệ chống lại sự gián đoạn):

cp -f foo foo.old &&
cut -d , -f 1,3 <foo.old >foo &&
rm foo.old

Tôi khuyên bạn nên sử dụng một trong các cutphương pháp dựa trên. Bằng cách đó, bạn không phụ thuộc vào bất kỳ công cụ không chuẩn nào, bạn có thể sử dụng công cụ tốt nhất cho công việc và bạn kiểm soát hành vi bị gián đoạn.


Tốt hơn .oldphương pháp thay đổi tại chỗ,echo "$(cut -d , -f 1,3 <foo)" > foo
GypsyCosmonaut

1
@GypsyCosmonaut Không, đây không phải là tốt hơn. Nó dễ vỡ hơn. Lợi ích duy nhất của nó là nó ngắn hơn để gõ. Vấn đề chính với phương pháp của bạn là nếu xảy ra lỗi trong khi xử lý tệp đầu vào hoặc ghi đầu ra, dữ liệu sẽ bị mất. Nó cũng không hoạt động với dữ liệu nhị phân: đầu ra sẽ bị cắt ở byte null đầu tiên. Ngay cả với các tệp văn bản, nó sẽ loại bỏ các dòng trống từ cuối tệp. Với các tệp lớn, nó có thể thất bại vì dữ liệu phải được lưu dưới dạng một chuỗi trong bộ nhớ của shell (và hãy nhớ, nếu điều này xảy ra, dữ liệu sẽ bị mất).
Gilles 'SO- ngừng trở nên xấu xa'

oO Cảm ơn, tôi không biết có thể có vấn đề với byte null
GypsyCosmonaut

Tôi nghĩ việc này đơn giản hơn:cut -d , -f 1,3 foo > foo.new rm foo mv foo.new foo
LoMaPh

@LoMaPh Thật vậy, tôi không biết tại sao tôi đổi tên tệp cũ: nó không có bất kỳ lợi thế nào so với việc đổi tên tệp mới. Nó cũng đơn giản hơn vì bạn không cần bước này rm foo. Và bạn không nên gọi rm foo, bởi vì mv foo.new foolà nguyên tử: nó loại bỏ phiên bản cũ và đặt phiên bản mới vào vị trí cùng một lúc.
Gilles 'SO- ngừng trở nên xấu xa'

23

Các moreutils gói từ ubuntu (và cũng debian ) có một chương trình gọi là sponge, mà sắp xếp của cũng giải quyết được vấn đề của bạn.

Từ người đàn ông bọt biển:

xốp đọc đầu vào tiêu chuẩn và ghi nó ra tập tin được chỉ định. Không giống như chuyển hướng shell, bọt biển thấm tất cả đầu vào của nó trước khi mở tệp đầu ra. Điều này cho phép hạn chế các đường ống đọc và ghi vào cùng một tệp.

Điều này sẽ cho phép bạn làm một cái gì đó như:

cut -d <delim> -f <fields> somefile | sponge somefile

9

Tôi không nghĩ rằng có thể sử dụng cutmột mình. Tôi không thể tìm thấy nó trong trang thông tin hoặc người đàn ông. Bạn có thể làm một cái gì đó như

mytemp=$(mktemp) && cut -d" " -f1 file > $mytemp && mv $mytemp file

mktemplàm cho bạn một tệp tạm thời tương đối an toàn mà bạn có thể dẫn cutđầu ra vào.


1

Hãy thử vim-way:

$ ex -s +'%!cut -c 1-10' -cxa file.txt

Điều này sẽ chỉnh sửa tập tin tại chỗ (vì vậy hãy sao lưu trước).

Hoặc sử dụng grep, sedhoặc gawk.


0

Bạn có thể sử dụng slurp với POSIX Awk:

cut -b1 file | awk 'BEGIN{RS="";getline<"-";print>ARGV[1]}' file

Thí dụ


0

Chà, vì cuttạo ra đầu ra ít hơn nó đọc, bạn có thể làm:

cut -c1 < file 1<> file

Đó là, làm cho stdin của nó filemở ở chế độ chỉ đọc và stdout của nó filemở ở chế độ đọc + ghi mà không cắt ( <>).

Bằng cách đó, cutsẽ chỉ ghi đè lên tệp. Tuy nhiên, nó sẽ để phần còn lại của tập tin không bị ảnh hưởng. Chẳng hạn, nếu filechứa:

foo
bar

Đầu ra sẽ trở thành:

f
b
bar

Các f\nb\nđã thay thế foo\n, nhưng barvẫn còn đó. Bạn cần cắt bớt tệp sau khi cuthoàn thành.

Với ksh93, bạn có thể làm điều đó với <>;toán tử của nó , hoạt động giống như <>ngoại trừ nếu lệnh thành công, ftruncate()được gọi trên bộ mô tả tệp. Vì thế:

cut -c1 < file 1<>; file

Với các shell khác, bạn cần thực hiện ftruncate()thông qua một số phương tiện khác như:

{ cut -c1 < file; perl -e 'truncate STDOUT, tell STDOUT';} 1<> file

mặc dù việc gọi perlchỉ vì điều đó là quá mức cần thiết ở đây, đặc biệt là xem xét perlcó thể dễ dàng thực hiện cutcông việc đó như:

perl -pi -e '$_ = substr($_, 0, 1)' file

Xin lưu ý rằng với tất cả các phương pháp liên quan đến việc viết lại tại chỗ thực tế, nếu hoạt động bị gián đoạn giữa chừng, bạn sẽ kết thúc với một tệp bị hỏng. Sử dụng một tập tin thứ hai tạm thời để tránh vấn đề này.

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.