xóa ký tự đầu tiên và ký tự cuối cùng của mỗi dòng khỏi dòng lệnh


8

Tôi đang cố gắng loại bỏ các ký tự đầu tiên và cuối cùng của mỗi dòng trong tệp văn bản và lưu phiên bản rút gọn trong một tệp mới. Có ai có ý tưởng về cách thực hiện điều đó một cách hiệu quả bằng cách sử dụng awkhoặc các chương trình / lệnh linux khác dành riêng cho các tệp lớn không?

input.txt

(s,2,4,5,6)
"s,1,5,5,2"
{z,0,4,5,3}
[y,2,4,5,5]
(y,4,4,5,7)
(r,20,4,5,7)
(e,9,4,5,2)

Dự kiến ​​output.txt

s,2,4,5,6
s,1,5,5,2
z,0,4,5,3
y,2,4,5,5
y,4,4,5,79
r,20,4,5,7
e,9,4,5,2

Câu trả lời:


14

Một cách khác chỉ dành cho cái quái của nó:

rev input | cut -c2- | rev | cut -c2-

(Lưu ý: với GNU cut, nó chỉ hoạt động đối với các ký tự chỉ được tạo bởi một byte (như trong ví dụ của bạn)).


Đẹp! Điều này là nhanh hơn đáng kể so với các giải pháp sed và awk đề xuất cho đến nay.
Gilles 'SO- ngừng trở nên xấu xa'

Tôi đã đề xuất câu trả lời này cho những người sợ cú pháp sed / awk / regex, nhưng sẽ không tưởng tượng được nó nhanh hơn, đặc biệt là đối với các tệp lớn, với ba ống dẫn và chuyển toàn bộ nội dung qua từng cái. Có thể nghĩ sed hoặc awk đọc một dòng tại một thời điểm sẽ hiệu quả hơn cho các tệp lớn.
Drake Clarris

3
Đoán rằng đó là hơn 40 năm tối ưu hóa của nhiều tiện ích * nix này sẽ giúp bạn có được!
Drake Clarris

@Gilles, nó nhanh hơn với GNU sed trong utf8 loc đối với một số dạng đầu vào và điều này phụ thuộc vào việc bạn đang xem xét thời gian đồng hồ treo tường hay thời gian CPU. ssedhoặc công cụ gia truyền sedcó thể đạt được hiệu suất tốt hơn.
Stéphane Chazelas

@Gilles Không có mục MAN nào cho rev trong Solaris 5.10. Tôi đã kết thúc bằng cách sử dụngsed
ayrton_senna

10

Theo bạn câu hỏi xóa từ cuối cùng và từ đầu tiên từ tập tin đầu vào như dưới đây:

sed 's/.$//; s/^.//' inputfile

Sẽ thật tuyệt nếu bạn có thể chấm điểm này so với giải pháp khác , s/.\(.*\).$/\1/. Nó có thể nhanh hơn trên tài khoản của việc không sử dụng phản hồi và câu hỏi đã đề cập đến "các tệp lớn".
l0b0

4
@ l0b0 Tôi đã thử nghiệm với time yes | head -n 10000000 | COMMAND >/dev/null. Tôi nhận được rev input | cut -c2- | rev | cut -c2-→ 0,14s, sed 's,.\(.*\).$,\1,'→ 3,38s; awk '{print substr($0,2,length()-2);}'→ 3,50 giây; sed 's/.$//; s/^.//'→ 5.09s.
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles +1 Đó phải là một câu trả lời.
l0b0

2
@Gilles, đó là những dòng rất ngắn. Tôi thấy rằng đối với các dòng rộng 30 ký tự, giải pháp của @ RahulPatil nhanh gấp 3 lần với GNU sed so với @ juampa. Cũng thế. sed 's/.\(.*\)./\1/'dường như nhanh hơn sed 's/^.\(.*\).$/\1/'(GNU sed một lần nữa). Ngoài ra, hiệu suất phụ thuộc vào miền địa phương (giải thích về ký tự là gì) và việc sedthực hiện (về mặt đó, sed từ công cụ gia truyền nhanh hơn đáng kể so với GNU sed).
Stéphane Chazelas

5

Có rất nhiều khả năng, như mọi khi

sed 's,.\(.*\).$,\1,g' your_file

Giải trình

  • , - dấu phân cách sed, cũng có thể là bất kỳ nhân vật nào khác, với điều kiện là nó được thoát ra bất cứ khi nào cần thiết.
  • . Phù hợp với một nhân vật
  • \(.*\) - Nhóm phần còn lại, và phần này được lưu trữ để lấy thêm.
  • . Ghép một ký tự một lần nữa
  • $ - Kết thúc dòng
  • \1 - xuất văn bản phù hợp theo nhóm ở trên
  • g thay thế trên toàn cầu trên dòng.

2
Tại sao g? sẽ chỉ có một trận đấu trên mỗi dòng.
njsg

Lưu ý rằng nó sẽ không xóa bất cứ thứ gì khỏi các dòng có ít hơn 2 ký tự.
Stéphane Chazelas

3

Bạn cũng có thể làm điều đó với awknếu bạn thích

awk '{print substr($0,2,length()-2);}' input.txt > output.txt

2
tr -d '()[]{}"' < your_file

Điều này sẽ làm việc như là tốt. Nó cũng "dịch" từng ký tự thành không có gì (xóa).

Nhược điểm là nó sẽ xóa chúng nếu chúng không phải là ký tự đầu tiên / cuối cùng. Nó cũng sẽ bỏ lỡ bất kỳ ký tự kết thúc nào bạn không liệt kê trong ()[....

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.