Làm cách nào tôi có thể chỉnh sửa n dòng cuối cùng trong một tệp?


10

Có lệnh nào cho phép tôi chỉnh sửa n dòng cuối cùng trong một tệp không? Tôi có một số tệp, tất cả đều có số dòng khác nhau bên trong. Nhưng tôi muốn sửa đổi n dòng cuối cùng trong mỗi tệp. Mục tiêu là thay thế dấu phẩy bằng dấu chấm phẩy ở n dòng cuối cùng. Nhưng chỉ trong n dòng cuối cùng.

Tôi không muốn xóa bất kỳ dòng nào, tôi chỉ muốn thay thế mỗi dấu phẩy bằng dấu chấm phẩy trong n dòng cuối cùng trong mỗi tệp.

Sử dụng lệnh sed tôi có thể thay thế dòng cuối cùng bằng lệnh này. Như được mô tả ở đây: Làm cách nào tôi có thể xóa văn bản trên dòng cuối cùng của tệp?

Nhưng điều này chỉ cho phép tôi sửa đổi dòng cuối cùng chứ không phải số n dòng cuối cùng.


1
Đơn giản chỉ cần sử dụng sed '24,$s/,/:/g' filename đâu 24là vạch xuất phát`
Valentin Bajrami

Câu trả lời:


13

Để thay thế dấu phẩy bằng dấu chấm phẩy trên n dòng cuối cùng bằng ed:

n=3
ed -s input <<< '$-'$((n-1))$',$s/,/;/g\nwq'

Tách nó ra:

  • ed -s = chạy ed im lặng (không báo cáo các byte được viết ở cuối)
  • '$-'= từ cuối tệp ( $) trừ ...
  • $((n-1)) = n-1 dòng ...
  • ( $' ... '= trích dẫn phần còn lại của lệnh để bảo vệ nó khỏi shell)
  • ,$s/,/;/g= ... cho đến khi kết thúc tệp ( ,$), tìm kiếm và thay thế tất cả dấu phẩy bằng dấu chấm phẩy.
  • \nwq = kết thúc lệnh trước, sau đó lưu và thoát

Để thay thế dấu phẩy bằng dấu chấm phẩy trên n dòng cuối cùng bằng sed:

n=3
sed -i "$(( $(wc -l < input) - n + 1)),\$s/,/;/g" input

Phá vỡ điều đó:

  • -i = chỉnh sửa tệp "tại chỗ"
  • $(( ... )) = làm một số phép toán:
  • $( wc -l < input) = lấy số lượng dòng trong tệp
  • -n + 1 = đi ngược dòng n-1
  • ,\$ = từ n-1 dòng cho đến khi kết thúc tệp:
  • s/,/;/g = thay thế dấu phẩy bằng dấu chấm phẩy.

Có thể thay thế wc -l < inputbằng wc -l input. Nên nhanh hơn vài nano giây :)
vườn

1
ngoại trừ việc wc -l inputxuất ra tên tệp là tốt; chúng tôi chỉ muốn đếm số dòng
Jeff Schaller

Lời khuyên đầu tiên với ed là tốt và đơn giản.
sku2003

Tôi thực sự đã nhận được sự giúp đỡ từ một phía hoàn toàn khác. Điều này dẫn đến đoạn mã kỳ lạ này, thực hiện thủ thuật nhưng dài và lạ. Tôi đoán đây là một số điều kỳ lạ mà bạn có thể kết thúc khi kết hợp một giải pháp. Dù sao thì cái của bạn đẹp hơn, ngắn hơn và ít phức tạp hơn của tôi: Mã ở đây cũng hoạt động:
sku2003

mèo đầu vào.file | sed 's /, /, \ n / g' | sed -n '1! G; h; $ p' | awk -vn = 2 'NR <= n {gsub (",", ";", $ 0)} {print}' | sed -n '1! G; h; $ p' | sed '/ ^ \ s * $ / d'> output.file
sku2003

6

Giải pháp sử dụng tacsed để thay thế mỗi dấu phẩy bằng dấu chấm phẩy trong 50 dòng file.txt cuối cùng:

tac file.txt | sed '1,50s/,/;/g' | tac

5

Với GNU headvà shell giống Bourne:

n=20
{ head -n -"$n"; tr , ';'; } < file 1<> file

Chúng tôi đang ghi đè lên tập tin. Điều đó ổn ở đây đối với chuyển ngữ từ byte sang byte nhưng sẽ không nhất thiết nếu việc sửa đổi ngụ ý thay đổi kích thước của tệp (trong trường hợp đó, bạn muốn thay thế 1<> filebằng > other-file && mv other-file fileví dụ).


1
Đây là tài liệu cho1<> , mà tôi không quen thuộc. Ngoài ra, spongetừ moreutils là một công cụ tốt cho các đường ống nơi bạn muốn ghi đè lên đầu vào của mình.
Miles

1

Giả sử chúng ta muốn thay thế các 7dòng cuối cùng của chuỗi sau bằng shell script và triển khai GNU của sed:

$ seq 20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Bước 1 : cho phép lấy số thứ tự dòng cuối cùng như sau. Hãy xem cái nàycái kia :

$ lastLine=`seq 20|sed -n '$='`

$ echo $lastLine 
20

Bước 2 : cho phép đặt số lượng dòng (ở cuối chuỗi) chúng tôi dự định chỉnh sửa:

$ numberOfLines=7

$ echo $numberOfLines 
7

Bước 3 : cho phép tính dòng bắt đầu dựa trên các biến trước đó, như sau. Hãy nhìn vào điều này :

$ startLine=`expr $lastLine - $numberOfLines + 1`

$ echo $startLine 
14

Bước 4 : Bây giờ, chúng ta có thể thay thế 7 dòng cuối cùng bằng một thứ khác, như sau. Hãy nhìn vào điều này :

$ seq 20|sed -e "$startLine,+$numberOfLines{s/[12]/WoW/}"
1
2
3
4
5
6
7
8
9
10
11
12
13
WoW4
WoW5
WoW6
WoW7
WoW8
WoW9
WoW0

Bước 4 đang sử dụng phần 4.4 của trang sed man có nội dung:

'ADDR1,+N'
     Matches ADDR1 and the N lines following ADDR1.

Bước 4, cũng đang sử dụng dấu ngoặc kép như được đề cập ở đây .


Chà, 4 bước là không cần thiết nếu chúng ta sử dụng câu trả lời của Gohu như thế này:

$ seq 20 |tac|sed -e '1,7{s/[12]/WoW/}'|tac
1
2
3
4
5
6
7
8
9
10
11
12
13
WoW4
WoW5
WoW6
WoW7
WoW8
WoW9
WoW0

0

Sử dụng tailvà đường ống để sed:

tail -n 20 file | sed 's/,/;/g'

Điều này hoạt động trên các tập tin cho 20 dòng cuối cùng. Nếu bạn muốn có các canges trực tiếp vào tập tin, hãy sử dụng:

tail -n 20 file | sed -i 's/,/;/g'

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.