2011-04-19 40 views
13

Tôi đã thấy nhiều biến thể, rất bối rối về cách giải quyết 3 vấn đề này.Xóa các dòng khỏi tệp với SED hoặc AWK

  1. xóa tất cả các hàng ngoại trừ người đầu tiên từ một tập tin
  2. xóa liên tiếp từ tập tin với một số dòng
  3. xóa các hàng từ một tập tin với một loạt các số dòng

Trả lời

24

Sử dụng sed:

Xóa dòng 1:

sed '1d' file-name 

Xóa dòng 10:

sed '10d' file-name 

Xóa dòng # 5 đến 10

sed '5,10d' file-name 

Tất cả trên lệnh sed sẽ viết ra trên stdout mà bạn có thể chuyển hướng đến một tập tin nếu bạn muốn hoặc sử dụng -i cờ của sed để chỉnh sửa nội tuyến tập tin.

+1

Để xóa * tất cả các dòng nhưng * * đầu tiên, 'sed' 2, $ d 'filename' hoặc' sed '1! d' filen ame', hoặc 'sed -n' 1p 'filename'. – Beta

+0

@Beta, đầu tiên hai là chính xác, nhưng thứ ba sẽ chỉ in dòng đầu tiên. – dubiousjim

+1

@dubiousjim: 'In dòng đầu tiên chỉ' giống như' xóa tất cả các dòng nhưng đầu tiên' đó là lý do tại sao 'sed -n '1p'' cũng chính xác. – anubhava

7

Với awk:

# delete line 1 
awk 'NR == 1 {next} {print}' file 

# delete line number stored in shell variable $n 
awk -v n=$n 'NR == n {next} {print}' file 

# delete between lines $a and $b inclusive 
awk -v m=$a -v n=$b 'm <= NR && NR <= n {next} {print}' file 

Để tiết kiệm một vài ký tự, {print} thể được thay thế chỉ với 1

Để ghi đè lên file gốc, bạn phải làm một cái gì đó như thế này

awk '...' file > tmpfile && mv tmpfile file 
+0

làm cách nào để tôi nhận được kết quả của việc không hiển thị? – bluetickk

+0

ok điều này đang hoạt động nhưng các dòng chỉ in ra và không lưu vào tệp? – bluetickk

+0

@bluetickk, đã cập nhật câu trả lời của tôi –

0

bạn chỉ có thể sử dụng bash nếu hệ thống của bạn có. Ý tưởng cơ bản đằng sau là đặt số lượng và tăng số lượng này trong khi lặp lại tệp.

1) xóa tất cả các hàng ngoại trừ người đầu tiên từ một tập tin

read -r line < file; echo "$line" > temp && mv temp file 

2) xóa một hàng từ tập tin với một số dòng

declare -i count=0 
while read -r line 
do 
    ((count++)) 
    case "$count" in 
    10) continue;; 
    *) echo "$line";; 
    esac 
done <file> temp && mv temp file 

3) xóa các hàng từ một tập tin với một loạt của các số dòng, ví dụ: từ 10 đến 20

declare -i count=0 
while read -r line 
do 
    ((count++)) 
    if (($c < 10 && $c > 20));then 
    echo "$line";; 
    fi 
done <file> temp && mv temp file 
+0

Cách bạn sử dụng nó, 'read -r' sẽ vẫn tách khoảng trống đầu và cuối. Bạn cần phải thực hiện 'IFS = read -r line'.Hơn nữa lưu ý rằng từ một kịch bản lệnh shell, phương thức này nhanh hơn cho các tệp nhỏ vì nó tránh được một ngã ba, nhưng chậm hơn cho các tệp lớn vì 'đọc' vốn không hiệu quả và thường đọc một byte tại một thời điểm hoặc thực hiện một cuộc gọi đọc và lseek cho mỗi lời gọi và xử lý chuỗi trong bash có xu hướng không hiệu quả (ít hơn trong các shell khác). – jilles

+0

@jilles, cảm ơn tôi đã quên về IFS = trong những trường hợp này. Và có, tôi biết rằng 'đọc' là không hiệu quả trên các tập tin lớn với' bash'. Nếu các tệp của OP có kích thước lớn và hiệu suất là một vấn đề thì hãy sử dụng một công cụ tốt hơn. –

Các vấn đề liên quan