it-swarm-eu.dev

Jak získat inverzní chování pro „ocas“ a „hlavu“?

Existuje způsob, jak head/tail dokument a získat zpětný výstup; protože nevíte, kolik řádků je v dokumentu?

Tj. Chci jen získat všechno kromě prvních 2 řádků foo.txt připojit k jinému dokumentu.

57
chrisjlee

Můžete použít k odstranění prvních dvou řádků:

tail -n +3 foo.txt

a tím se odstraní poslední dva řádky:

head -n -2 foo.txt

(za předpokladu, že soubor končí znakem \n pro pozdější)


Stejně jako pro standardní použití tail a head tyto operace nejsou destruktivní. Použijte >out.txt pokud chcete přesměrovat výstup na nový soubor:

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

V případě out.txt již existuje, tento soubor přepíše. Použijte >>out.txt namísto >out.txt pokud byste raději nechali výstup připojit k out.txt.

59

Pokud chcete všechny kromě prvních N-1 řádků, volejte tail s počtem řádků +N. (Číslo je číslo prvního řádku, který chcete zachovat, počínaje 1, tj. +1 znamená začátek nahoře, +2 znamená přeskočení jednoho řádku atd.).

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

Neexistuje snadný, přenosný způsob, jak přeskočit posledních N linek. GNU head umožňuje head -n +N jako protějšek tail -n +N. Jinak, pokud máte tac (např. GNU nebo Busybox), můžete jej kombinovat s ocasem:

tac | tail -n +3 | tac

Přenosně můžete použít filtr awk (netestovaný):

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

Pokud chcete odstranit několik posledních řádků z velkého souboru, můžete určit bajtový offset kusu, který se má zkrátit, a pak provést zkrácení pomocí 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))"

Na začátku nemůžete zkrátit soubor na místě, ale pokud potřebujete odstranit několik prvních řádků obrovského souboru, můžete přesunout obsah .

Ze stránky tail man (GNU tail, to je):

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

Následující text by tedy měl připojit všechny kromě prvních 2 řádků somefile.txt to anotherfile.txt:

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

K odstranění prvních n řádků GNU sed. Například pokud n = 2)

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

The ! znamená "vyloučit tento interval". Jak si dokážete představit, lze získat například složitější výsledek

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

který zobrazí řádek 3,4,5,7. Více energie pochází z používání regulárních výrazů namísto adres.

Omezení spočívá v tom, že čísla linek musí být známa předem.

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

Pokud je <infile normální, lseek() - schopný soubor, pak ano, v každém případě, klidně. Výše uvedené je plně POSIXem podporovaný konstrukt.

2
mikeserv

Zatímco tail -n +4 pro výstup souboru začínajícího na 4. řádku (všechny kromě prvních 3 řádků) je standardní a přenosný, jeho protějšek head (head -n -3, všechny kromě posledních 3 řádků) nejsou.

Přenosně byste udělali:

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

Nebo:

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

(pozor, že v některých systémech, kde sed má vzorový prostor omezené velikosti, který se nezmění na velké hodnoty n).

Nebo:

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

Pomocí diff můžete porovnat výstup head/tail s původním souborem a poté odstranit, co je stejné, a získat tak inverzi.

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

Můj přístup je podobný jako Gilles, ale místo toho jen převracím soubor s kočkou a dýmkou, že s příkazem head.

tac -r thefile.txt | head thisfile.txt (nahrazuje soubory)

0
Abe

Řešení pro BSD (macOS):

Odebrat první 2 řádky:

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

Odebrat poslední 2 řádky:

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

... není moc elegantní, ale dělá svou práci!

0
spectrum

Doufám, že jsem jasně pochopil vaši potřebu.

Máte několik způsobů, jak vyplnit svůj požadavek:

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

Kde / etc/passwd je váš soubor

Druhé řešení může být užitečné, pokud máte obrovský soubor:

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