it-swarm-tr.com

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

Bir dokümanı head/tail hale getirmenin ve ters çıktıyı almanın bir yolu var mı; çünkü bir belgede kaç satır olduğunu bilmiyorsunuz?

Yani Ben sadece foo.txt İlk 2 satır dışında her şeyi başka bir belgeye eklemek istiyorum.

57
chrisjlee

Bunu ilk iki satırı soymak için kullanabilirsiniz:

tail -n +3 foo.txt

ve bu son iki satırı soymak için:

head -n -2 foo.txt

(dosyanın ikincisi için \n ile bittiği varsayılarak)


Tıpkı tail ve head standart kullanımında olduğu gibi, bu işlemler yıkıcı değildir. Çıkışı yeni bir dosyaya yeniden yönlendirmek istiyorsanız >out.txt Kullanın:

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

out.txt Zaten mevcutsa, bu dosyanın üzerine yazılır. Çıktıya >>out.txt Eklenmesini istiyorsanız, >out.txt Yerine out.txt Kullanın.

59
Stéphane Gimenez

İlk N-1 satırları hariç tümünü istiyorsanız, satır sayısını +N İle tail çağırın. (Sayı, 1'den başlayarak korumak istediğiniz ilk satırın numarasıdır, yani +1 en üstte 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 head, head -n +N 'Nin karşılığı olarak tail -n +N' A izin verir. Aksi takdirde, tac (örneğin GNU veya Busybox) ile kuyrukla birleştirebilirsiniz:

tac | tail -n +3 | tac

Portably, bir awk filtresi (denenmemiş) kullanabilirsiniz:

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

Büyük bir dosyadan son birkaç satırı kaldırmak isterseniz, kesilecek parçanın bayt uzaklığını belirleyebilir ve ardından kesmeyi dd ile yapabilirsiniz.

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 bir dosyayı yerinde kesemezsiniz, ancak büyük bir dosyanın ilk birkaç satırını kaldırmanız gerekiyorsa, içeriği taşıyabilirsiniz .

tail man sayfasından (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ğıdakiler somefile.txt Öğesinin ilk 2 satırı dışındaki tüm satırlarını anotherfile.txt Öğesine eklemelidir:

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

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

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

! "bu aralığı hariç tut" anlamına gelir. Tahmin edebileceğiniz gibi, daha karmaşık bir sonuç elde edilebilir, örneğin

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

3,4,5,7 satırını gösterecektir. Adresler yerine normal ifadelerin kullanımından daha fazla güç gelir.

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

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

<infile normalse, lseek() - mümkün bir dosyaysa, evet, elbette çekinmeyin. Yukarıdaki tamamen POSIXly destekli bir yapıdır.

2
mikeserv

Süre tail -n +4 dosyasını 4. satırdan başlayarak (ilk 3 satır hariç tümü) standart ve taşınabilir, head karşılığı (head -n -3, son 3 satır hariç tümü) değildir.

Taşınabilir bir şekilde şunları yaparsınız:

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

Veya:

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

(sed 'nin büyük boyutta n değerine ölçeklenmeyen bir desen alanına sahip olduğu bazı sistemlerde dikkat edin).

Veya:

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

diff/head çıktısını orijinal dosyayla karşılaştırmak için tail kullanabilirsiniz ve sonra aynı olanı kaldırarak tersine çevirin.

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

Benim yaklaşımım Gilles'e benziyor ama bunun yerine dosyayı cat komutuyla tersine çeviriyorum.

tac -r thefile.txt | head thisfile.txt (dosyaları değiştirir)

0
Abe

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

İlk 2 satırı kaldırın:

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 zarif değil ama işi hallediyor!

0
spectrum

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

/ etc/passwd dosyanızdır

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
Mathieu Coavoux