cat komutundan ilk X karakterini al?


41

Benim kabuk betiğimde bir değişkene çıktığım bir metin dosyası var. Ancak ilk 50 karaktere ihtiyacım var.

Kullanmayı denedim cat ${filename} cut -c1-50ama ilk 50 karakterden çok daha fazlasını alıyorum? Bu, cutmetinler bir uzun dize olabilirken, satır aramaya (% 100 kesin değil) bağlı olabilir, gerçekten de buna bağlı.

İlk X karakterini bir catkomuttan almak için kullanabileceğim bir yardımcı program var mı?


10
Unuttun |mu cat ${filename} | cut -c1-50
DisplayName

@ GösterimAdı düzeltildi, yeniden yazma hatamı yakaladığınız için teşekkürler.
jkj2000 13:14

1
@ jkj2000, eski soru olduğu gibi eski sürüme geri döndüm.
Ramesh

Yanıtlar:


61
head -c 50 file

Bu ilk 50 baytı döndürür.

Komutun her zaman tüm işletim sistemlerinde aynı şekilde kullanılmadığına dikkat edin. Linux ve macOS'ta bu şekilde davranır. Solaris'te (11) / usr / gnu / bin / dizinindeki gnu sürümünü kullanmanız gerekir.


kafanın başka -cseçeneği yok . Bunun yerine dd (1) için giderdim .
mirabilos

6
Bu cevabın, OP'nin bayt değil, ilk X karakteri için sorulduğu gibi, dosyanın yalnızca ASCII karakterleri içerdiğini varsaydığını unutmayın.
Calimo

2
@mirabilos Taşınabilir olmayabilir, ancak sürümüm ( GNU coreutils 5.97) var.
Yossarian

1
POSIX -cgeçerli bir seçenek olarak tanımlamamaktadır , bu yüzden kesinlikle yerel ortamınıza bağlıdır. unix.com/man-page/posix/1/head
Jules

1
@Calimo Evet, biliyorum ama 100 karakterden oluşan bir metin dosyası oluşturup daha sonra komutumu çalıştırmayı denedim ve 50 karakter yazdırdı. Ama ASCII konusunda haklısın, ancak OP bunu cevaplandığı gibi işaretlediğinden beri davasında hiçbir şey yoktu.
DisplayName

27

Sizin cutbuna veri aktarmak için bir boru kullanıyorsanız komut çalışır:

cat ${file} | cut -c1-50 

Ya da, işe yaramaz kedi kullanmaktan kaçınmak ve onu biraz daha güvenli kılmak:

cut -c1-50 < "$file"

Yukarıdaki komutların her bir giriş satırının ilk 50 karakterini (veya cutuygulamanıza bağlı olarak baytları) yazacağını unutmayın . Dosyanız çok büyük bir satırsa, dediğiniz gibi, beklediğiniz şeyi yapmalıdır.


8
dd status=none bs=1 count=50 if=${filename}

Bu ilk 50 baytı döndürür.


dd'ninstatus=none bayrağı yoktur . 2>/dev/nullBunun yerine kullanın (ve uygun şekilde alıntı yapın): dd if="$filename" bs=1 count=50 2>/dev/null(yine de bs=50 count=1dahil olan sistem çağrı sayısını azaltmak için kullanmayı düşünün ).
mirabilos

1
@mirabilos dd, status=none8.21 Ubuntu 14.04 , coreutils kullanırken sahip olur, ancak 2>/dev/nulldaha eski bir sürüm kullanıyorsanız kullanmakta haklısınız .
doneal24

1
@mirabilos Çoğu Linux dağıtımı, FreeBSD ve diğer BSD'ler gibi GNU coreutillerini kullanır. Solaris'te gnu-coreutils paketi olarak bulunur. Evet, bu "Unix ve Linux" ve hem Unix hem de Linux sistemleri GNU coreutils kullanıyor.
doneal24

2
Hayır, Unix sistemleri genellikle GNU yardımcı programlarını kullanmaz. GNU, “GNU Unix değil” in bile kısaltmasıdır. Lütfen taşınabilir çözümlere bağlı kalın ya da yalnızca GNU çözümleri vermek zorundaysanız , belirtin ve mümkünse eşdeğer bir taşınabilir çözüm gösterin.
mirabilos

1
Açıkçası, bu read()50 bayttan birini yapar . Eğer fileörnek daha az karaktere yönelik bir boru anda mevcut olan, daha sonra daha az bayt döndürülür. Eşdeğerine sahip olmak için head -c50, GNU'ya özgü kullanmanız gerekir iflag=fullblock.
Stéphane Chazelas 21:14

4

Şimdiye kadar cevapların çoğu, ASCII olmayan bir yerel ayar kullanıyorsanız, bu durumun 1 bayt = 1 karakter olduğunu varsayar.

Bunu yapmak için biraz daha sağlam bir yol:

testString=$(head -c 200 < "${filename}") &&
  printf '%s\n' "${testString:0:50}"

Bunun varsayıldığına dikkat edin:

  1. Kullanıyorsunuz ksh93, bash(veya yeni zshya mkshtarafından desteklenen tek multi-byte karakter kümesi olsa ( mkshUTF-8 ve ancak sonradır set -o utf8-modeve bir versiyonu)) heado desteklerin -c(çoğu günümüzde, ama kesinlikle standart değildir).
  2. Geçerli yerel ayar, dosya ile aynı kodlamaya ayarlanmış ( bunu kontrol etmek için yazın locale charmapve file -- "$filename"yazın); değilse, yani ile ayarlayın. LC_ALL=en_US.UTF-8)
  3. headTüm karakterlerin en fazla 4 baytta kodlandığı en kötü UTF-8 kodunu varsayarsak , dosyanın ilk 200 baytını aldım . Bu, düşünebildiğim çoğu durumu kapsamalı.

Tabii ki, bu aynı zamanda GNU’yu headya da nnn standart -cseçeneğini ekleyen başka bir uygulamasını da varsayar . Ama zaten GNU bash gerektiriyor. (Not: mkshUTF-8 modu UTF-8 kodlu dosyalar için bunu yapabilir.) OP'e sekizli veya çok baytlı karakterler gerektirip gerekmediğini sorardım, sadece “karakterler” belirsiz / genel bir terimdir.
mirabilos

Bu da boş newline veya joker karakterler içerdiğini $filenameveya $testStringbulunmadığını veya başladığını varsayar -.
Stéphane Chazelas

${var:offset:length}Burada kullandığınız yapı aslında gelir ksh93ve ayrıca son sürümlerinde desteklenir zsh( zshkendi vardır $testString[1,50]). İhtiyacınız ${testString:0:50} içinde ksh93ve zshbununla birlikte.
Stéphane Chazelas 21:14

Sadece yukarıdaki yorumları ele almak için cevabımı düzenledi
Calimo

2
grep -om1 "^.\{50\}" ${filename}

Diğer değişken (dosyadaki ilk satır için)

(IFS= read -r line <${filename}; echo ${line:0:50})

Bu, yüksek seviye araçların kötüye kullanılmasıdır - ve örneğin yerel olarak farkındalarsa, istediğinizi yapmamaya meyillidir.
mirabilos

@mirabilos Üst düzey araçlar altında neyi kastediyorsunuz : readve echo? Ya da bash expansion?
Costas,

grep(regexp) ve evet, burada kabuğun kullanımı (ipucu: ilk satır büyük olabilir). (Söylendiği gibi, bashism de POSIX'te değildir, ancak çoğu deniz kabukları bunu uygular.)
mirabilos

0

ASCII dosyaları için 1. do @DisplayName gibi diyor ki:

head -c 50 file.txt

Örneğin, file.txt'nin ilk 50 karakterini yazdıracaktır.

2. İkili veriler için, hexdumpaltıgen karakter olarak yazdırmak için kullanın :

hexdump -n 50 -v file.bin

Örneğin, ilk 50 bayt file.bin 'in çıktısını alacaktır.

-vAyrıntılı seçenek olmadan, hexdumptekrarlanan satırların *bunun yerine yıldız ( ) ile değiştirileceğini unutmayın . Buraya bakınız: https://superuser.com/questions/494245/what-does-an-asterisk-mean-in-hexdump-output/494613#494613 .


-2

Sorunu oldukça kolay çözecek olan için sed kullanabilirsiniz

sed -e 's/^\(.\{50\}\).*/\1/' yourfile

OP'nin sorusunu çözerse, bunun nasıl düşürüldüğünü bilmek meraklı: "Sadece ilk 50 karaktere ihtiyacım var" Bu UUOC (İstenmeyen Kedi Kullanımı) olmadan ne istendiğini başarır
munkeyoto 15

1
Bu cevap, dosyanın ilk 50'sini değil, dosyadaki her satırın ilk elli karakterini verir. Ayrıca, tüm satırlar 50 karakterden kısa olduğunda hiçbir şey yazdırmaz. sed -n -e '1s/^\(.\{50\}\).*/\1/p' ${filename}
Çözümünle

Anlaşılması sadece olabilirdi: head -n 1 | sed -e 's / ^ (. \ {50 \}). * / \ 1 /' ... Ve bu sorunu çözecekti. OP şöyle demiştir: "Sadece ilk 50 karakter ihtiyaç"
munkeyoto

1
Hayır! İlk satır sadece 49 karakter uzunluğundaysa hiçbir şey çıkmaz.
doneal24

Doug Bunu ilk defa anladım, ancak OP 50 satırdan az çizgi içeriyorsa OP baskı işlemiyle ilgili hiçbir şeyden bahsetmedi, bu yüzden hala noktanızı görmedim ya da bunun düşünüldüğü nokta yine de çalışacak olanın içine düştü head: head -n 1 $ {dosyaadı} | sed -n-e '1 s / ^ (\ {50 \}). * / \ 1 / s.'
munkeyoto
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.