“Kuyruk” ve “kafa” için ters davranış nasıl elde edilir?


55

Belge head/ tailbelge ve ters çıktı almak için bir yolu var mı ; çünkü bir belgede kaç satır olduğunu bilmiyorsunuz?

Yani sadece foo.txtbaşka bir belgeye eklemek için ilk 2 satır dışında her şeyi almak istiyorum .

Yanıtlar:


57

Bunu ilk iki satırı sıyırmak için kullanabilirsiniz :

tail -n +3 foo.txt

ve bu son iki satırı sıyırmak için :

head -n -2 foo.txt

(dosyanın \nsonuncusu için bittiğini varsayarsak )


Tıpkı standart kullanım için olduğu gibi tailve headbu işlemler yıkıcı değildir. >out.txtÇıktıyı yeni bir dosyaya yönlendirmek istiyorsanız kullanın :

tail -n +3 foo.txt >out.txt

Durumda out.txtzaten var, bu dosyanın üzerine olacaktır. Çıktının eklenmesini tercih ediyorsanız >>out.txtyerine kullanın .>out.txtout.txt


3
re "head, dosya bittiğinde \n" .. Sadece hiçbir şey-n -0 döndürmeyen tüm negatif tamsayılar için çalışır , tıpkı (kullanarak: head (GNU coreutils) 7.4) ... Ancak bir iz varsa , yazdırır. yani beklenebileceği gibi . tüm dosyayı yazdırır ... Bu yüzden sıfır olmayan tüm negatif değerler için işe -n 0\n-n -0--0\n
yarar

@fred: Gerçekten garip… (burada 8.12 ile aynı).
Stéphane Gimenez

Bu operasyon yıkıcı mı? Belgenin ilk iki satırının tersini diğerine kopyalamak istediğim gibi mi?
chrisjlee

@Chris: Hayır, sonucu genellikle terminale bağlı olan "standart çıktı" üzerine yazdırırlar. Çıktının bazı dosyalara nasıl yönlendirileceğiyle ilgili bazı detaylar ekledim.
Stéphane Gimenez

7
head -n -2POSIX uyumlu değil .
l0b0

9

İlk N-1 satırları dışında tümünü istiyorsanız tail, satır sayısını arayın +N. (Sayı, tutmak istediğiniz ilk satırın numarasıdır, 1'den başlar, yani +1 en baştan başlar, +2 bir satır atlar vb. Anlamına gelir).

tail -n +3 foo.txt >>other-document

Son N satırını atlamanın kolay ve taşınabilir bir yolu yoktur. GNU karşılığı olarak headizin verir . Aksi takdirde, (örneğin GNU veya Busybox) varsa, kuyruğu ile birleştirebilirsiniz:head -n +Ntail -n +Ntac

tac | tail -n +3 | tac

Taşınabilir bir awk filtresi kullanabilirsiniz (denenmemiş):

awk -vskip=2 '{
    lines[NR] = $0;
    if (NR > skip) print lines[NR-skip];
    delete lines[NR-skip];
}'

Son birkaç satırı büyük bir dosyadan kaldırmak isterseniz, kesilecek parçanın bayt ofsetini belirleyebilir ve sonra kesmeyi gerçekleştirebilirsiniz dd.

total=$(wc -c < /file/to/truncate)
chop=$(tail -n 42 /file/to/truncate | wc -c)
dd if=/dev/null of=/file/to/truncate seek=1 bs="$((total-chop))"

Başlangıçta yerinde bir dosyayı kesemezsiniz, ancak büyük bir dosyanın ilk birkaç satırını kaldırmanız gerekirse , içeriği hareket ettirebilirsiniz .


Bazı sistemlerde (modern Linux gibi), başında bir dosyayı yerinden kesebilir (daraltabilirsiniz), ancak genellikle yalnızca FS bloğu boyutunun katları kadar bir miktarda (bu durumda gerçekten kullanışlı değildir).
Stéphane Chazelas

3

Gönderen tailadam sayfasında (GNU tail, yani):

-n, --lines=K
   output the last K lines, instead of the last 10; or use -n +K to
   output lines starting with the Kth

Bu nedenle, aşağıdakilerin tümü, ilk 2 satırından başka bir somefile.txtyere eklenmelidir anotherfile.txt:

tail --lines=+3 somefile.txt >> anotherfile.txt

3

İlk n çizgisini kaldırmak için GNU sed kullanılabilir. Örneğin n = 2 ise

sed -n '1,2!p' input-file

!Ortalama "Bu aralığı dışlamak". Tahmin edebileceğiniz gibi, örneğin daha karmaşık bir sonuç elde edilebilir.

sed -n '3,5p;7p'

bu satır 3,4,5,7 gösterecek. Daha fazla güç, adres yerine normal ifadelerin kullanılmasından kaynaklanır.

Sınırlama, satır numaralarının önceden bilinmesi gerektiğidir.


1
Neden sadece değil sed 1,2d? Daha basit genellikle daha iyidir. Ayrıca, örneklerinizde hiçbir şey GNU Sed'e özgü değildir; Komutlarınızın hepsi Sed'in standart POSIX özelliklerini kullanıyor .
Joker

1

Sen kullanabilirsiniz diffçıktısını karşılaştırmak head/ ' taildolayısıyla tersini alma, orijinal dosyaya ve daha sonra aynı olanı kaldırın.

diff --unchanged-group-format='' foo.txt <(head -2 foo.txt)

1

İken tail -n +4çıkışına dosya (bütün ilk 3 hatlarında ama) standart ve taşınabilir 4 satırdan, onun headmuadili ( head -n -3son 3 hatları ancak tümü) değil.

Taşınabilir olarak, yapardın:

sed '$d' | sed '$d' | sed '$d'

Veya:

sed -ne :1 -e '1,3{N;b1' -e '}' -e 'P;N;D'

( sedSınırlı büyüklükte bir desen alanına sahip, büyük değerlere ölçeklendirmeyen bazı sistemlerde dikkat edin n).

Veya:

awk 'NR>3 {print l[NR%3]}; {l[NR%3]=$0}'

1
{   head -n2 >/dev/null
    cat  >> other_document
}   <infile

Eğer <infiledüzenli olduğu lseek()sıfat daha dosya, o zaman evet, elbette, çekinmeyin. Yukarıdakiler tamamen POSIX destekli bir yapıdır.


0

Yaklaşımım Gilles'a benziyor ancak bunun yerine dosyayı yalnızca baş komutuyla aynı kedi ve boru ile tersine çeviriyorum.

tac -r Instagram Hesabındaki Resim ve Videoları thefile.txt head thisfile.txt (dosyaları değiştirir)


0

Umarım ihtiyacınızı açıkça anladım.

İsteğinizi yerine getirmenin birkaç yolu var:

tail -n$(expr $(cat /etc/passwd|wc -l) - 2) /etc/passwd

Dosyanız / etc / passwd nerede?

Çok büyük bir dosyanız varsa 2. çözüm yararlı olabilir:

my1stline=$(head -n1 /etc/passwd)
my2ndline=$(head -n2 /etc/passwd|grep -v "$my1stline")
cat /etc/passwd |grep -Ev "$my1stline|$my2ndline"

0

BSD için Çözüm (macOS):

İlk 2 satırı kaldır:

tail -n $( echo "$(cat foo.txt | wc -l)-2" | bc )

Son 2 satırı kaldır:

head -n $( echo "$(cat foo.txt | wc -l)-2" | bc )

... çok şık değil ama işi halleder!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.