Część 1
Po prostu d
usuń 13. linię:
sed '13d' <file.txt
Ogólnym sposobem na uzupełnienie powyższych jest:
sed '13!d' <file.txt
Część 2
Ponieważ można to zrobić:
sed -n ':a;${P;q};N;4,$D;ba' <file.txt
Zwróć uwagę, że 4
jest to jeden więcej niż wymagany numer. Więc jeśli chcesz ostatnią 10. linię, byłoby to 11
.
Testowanie z seq
:
$ seq 100 | sed -n ':a;${P;q};N;4,$D;ba'
98
$
Próba wyjaśnienia
:a # define label a
${ # match the last line
P # print the first line of the pattern space
q # quit
}
N # match all lines: append the next line to the pattern
4,${ # match the range of lines 4 to the end of the file
D # delete the first line of the pattern space
}
ba # match all lines: jump back to label a
Cenny dodatek Glenna Jackmana:
To był „tylko N-ty wiersz”. Oto „wszystko, ALE N-ta linia”:
sed -n ':a;${s/^[^\n]*\n//;p;q};N;4,${P;D};ba'
działa z GNU sed, \n
sekwencja może nie działać z innymi seds.
Próbowałem tego z BSD sed (OSX) i okazało się, że nie działało to w powyższej formie. Problemy wydają się być następujące:
;
używane do oddzielania linii wydaje się ogólnie działać, ale nie działa po etykiecie
- BSD sed wydaje się wymagać
;
po ostatnim poleceniu w {}
jednowierszowej grupie poleceń, podczas gdy GNU sed nie
\n
można na ogół stosować w wyrażeniu regularnym, ale najwyraźniej nie w []
wyrażeniu nawiasowym. Aby wykluczyć [[:alnum:][:punct:][:graph:][:blank:]]
znaki nowej linii, możemy użyć czegoś podobnego zamiast tego, chociaż może to wykluczać inne znaki (w szczególności inne znaki kontrolne).
Jest to więc próba wersji bardziej niezależnej od platformy:
sed -n ':a
${s/^[[:alnum:][:punct:][:graph:][:blank:]]*\n//p;q;};N;4,${P;D;};ba'
Wygląda na to, że działa pod OSX i Ubuntu.
head
/tail
jest znacznie wolniejsze niżsed
rozwiązanie. W każdym razie dzięki.