Dosyanın sonunda boş satırları olan bir dosya var. grep
Dosyanın sonunda komut dosyasında değişken olarak iletilen boş satır sayısını saymak için kullanabilir miyim ?
grep
@MichaelJohn kitabımda saflık için kazandı istedi .
Dosyanın sonunda boş satırları olan bir dosya var. grep
Dosyanın sonunda komut dosyasında değişken olarak iletilen boş satır sayısını saymak için kullanabilir miyim ?
grep
@MichaelJohn kitabımda saflık için kazandı istedi .
Yanıtlar:
Boş satırlar yalnızca sonundaysa
grep -c '^$' myFile
veya:
grep -cx '' myFile
grep -cv . myFile
(kod golfçüler için) yazmanın başka bir yoludur. Ancak grep
dosyanın herhangi bir yerinde boş satır varsa bir çözüm buldum .
grep -cv .
yalnızca geçerli karakterler oluşturmayan bayt içeren satırları da sayar.
Sadece eğlence için, ürkütücü sed
:
#!/bin/sh
sed '/./!H;//h;$!d;//d;x;s/\n//' "$1" | wc -l
Açıklama:
/./
herhangi bir karaktere sahip satırları adresler, böylece /./!
boş olmayan satırları adresler; olanlar için, H
komut tutun uzaya onları ekleyin. Bu nedenle, her boş satır için tutma alanına bir satır eklediysek, her zaman boş satır sayısından bir satır daha fazla olur. Daha sonra ilgileneceğiz.//h
boş desen, herhangi bir karakter olan son normal ifadeyle eşleşir, bu nedenle boş olmayan herhangi bir satır adreslenir ve toplanan satırları 1'e "sıfırlama" komutu ile bekleme alanına taşınırh
. Bir sonraki boş satır ekleneceği zaman, beklendiği gibi yine iki tane olacak.$!d
komut dosyasını son satır hariç her biri için çıktı olmadan durdurur, bu nedenle başka komutlar yalnızca son satırdan sonra yürütülür. Bekletme alanında topladığımız boş satırlar dosyanın sonundadır. İyi.//d
: d
Komut yalnızca boş olmayan satırlar için tekrar yürütülür. Eğer son satır boş değilse, sed
herhangi bir çıktı olmadan çıkacaktır. Sıfır çizgiler. İyi.x
borsalar boşluk ve desen alanı tutar, böylece toplanan çizgiler şimdi işlenecek desen alanındadır.s/\n//
.wc -l
.Biraz daha GNU tac
/ tail -r
seçenek:
tac file | awk 'NF{exit};END{print NR?NR-1:0}'
Veya:
tac file | sed -n '/[^[:blank:]]/q;p' | wc -l
Şunlara dikkat edin:
printf 'x\n '
Yani, son tam satırdan sonra fazladan bir boşluk varsa (bazıları ekstra boş satır olarak kabul edilebilir, ancak POSIX metnin tanımı ile geçerli metin değildir), bunlar 0 verir.
POSIXly:
awk 'NF{n=NR};END{print NR-n}' < file
ancak bu, dosyanın tam olarak okunması anlamına gelir ( tail -r
/ tac
dosyayı aranabilir dosyalarda sondan geriye doğru okur). Bu 1
çıktı verir printf 'x\n '
.
Aslında bir grep
çözüm istediğin için bunu sadece GNU'ya dayanıyorum grep
(tamam, ayrıca kabuk sözdizimi ve echo
... kullanarak ):
#!/bin/sh
echo $(( $(grep -c "" "$1") - $(grep -B$(grep -cv . "$1") . "$1" |grep -c "") ))
Burada ne yapıyorum? $(grep -c ".*" "$1")
dosyadaki tüm satırları sayar, ardından dosyayı boş satırlar olmadan özetleriz.
Ve bunları nasıl edinebilirim? $(grep -B42 . "$1"
boş olmayan satırlardan ve 42 satırdan önce grep olur, bu nedenle boş olmayan bir satırdan önce arka arkaya 42'den fazla boş satır olmadığı sürece her şeyi son boş olmayan satıra kadar basar. Bu sınırı önlemek $(grep -cv . "$1")
için -B
, toplam boş satır sayısı olan seçenek için parametre olarak alıyorum , bu yüzden her zaman yeterince büyük. Bu şekilde boş satırları çıkardım |grep -c ".*"
ve satırları saymak için kullanabilirim .
Harika, değil mi? (-;
tac | grep
ilk boş olmayan -m -A 42
, daha sonra eksi bir olana olacaktır. Hangisinin daha verimli olduğundan emin değilim, ama wc -l | cut -d' ' -f1
boş satırları selamlamak yerine?
tac
, wc
ve cut
, ama burada kendimi kısıtlamak için çalıştı grep
. Buna sapıklık diyebilirsiniz, buna spor diyorum. (-;
Başka bir awk
çözüm. Bu varyasyon k
, boş olmayan her satır olduğunda sayacı sıfırlar . Ardından, her satır sayacı artırır. (Yani, boş olmayan ilk uzunluk çizgisinden sonra k==0
.) Sonunda saydığımız satır sayısını çıkarırız.
Veri dosyasını hazırlayın
cat <<'X' >input.txt
aaa
bbb
ccc
X
Örnekteki boş satırları sayma
awk 'NF {k=-1}; {k++}; END {print k+0}' input.txt
3
Bu tanımda, boş bir satır boşluklar veya başka boş karakterler içerebilir; hala boş. Eğer gerçekten boş satırları yerine boş satırlar, değişiklik saymak istiyorsanız NF
için $0 != ""
.
$0 > ""
? Bu, birçok uygulamada kullanılandan strcoll()
daha az verimli $0 != ""
olan kullanımlar kullanır memcmp()
(POSIX, bunun kullanılmasını gerektirir strcoll()
).
$0 > ""
farklı olabileceğini düşünmedim $0 != ""
. awk
Yine de "yavaş" bir operatör gibi davranmaya eğilimliyim (giriş olarak büyük bir veri setim olduğunu ve işlemin zaman açısından kritik olduğunu bilirsem, miktarı azaltmak için neler yapabileceğimi göreceğim awk
- I bu grep | awk
gibi durumlarda yapıları kullanmıştır ). Ancak, ne varsayalım hızlı bir göz vardı POSIX tanımı ya herhangi bir referans göremiyorum strcoll()
ya memcmp()
. Neyi kaçırıyorum?
strcoll()
== dizeler, yerel ayara özgü harmanlama sırası kullanılarak karşılaştırılacaktır . Önceki sürümle karşılaştırın . Onu ben yetiştirdim. Ayrıca bkz. Austingroupbugs.net/view.php?id=963
a <= b && a >= b
, mutlaka aynı olmadığı bir uygulama a == b
. Ah!
awk
veya bash
(onun için [[ a < b ]]
için örneğin GNU sistemlerinde en_US.UTF-8 yerellerde operatörler) ①
vs ②
örneğin (için bash
hiçbiri, <
, >
, =
olanlar için gerçek dönmek). Tartışmalı bir şekilde bu yerlerin tanımında bash /
dosyanın sonundaki ardışık boş satır sayısını saymak için
Katı awk
+ tac
çözelti:
Örnek input.txt
:
$ cat input.txt
aaa
bbb
ccc
$ # command line
Eylem:
awk '!NF{ if (NR==++c) { cnt++ } else exit }END{ print int(cnt) }' <(tac input.txt)
!NF
- geçerli satırın boş olmasını sağlar (alan içermez)NR==++c
- boş satırların art arda sıralanmasını sağlamak. ( NR
- kayıt numarası, ++c
- eşit olarak artırılmış yardımcı sayaç)cnt++
- boş satır sayacıÇıktı:
3
IIUC, şu komut dosyası denir count-blank-at-the-end.sh
:
#!/usr/bin/env sh
count=$(tail -n +"$(grep . "$1" -n | tail -n 1 | cut -d: -f1)" "$1" | wc -l)
num_of_blank_lines=$((count - 1))
printf "%s\n" "$num_of_blank_lines"
Örnek kullanım:
$ ./count-blank-at-the-end.sh FILE
4
Bunu test GNU bash
, Android mksh
ve de ksh
.
Alternatif Python
çözüm:
Örnek input.txt:
$ cat input.txt
aaa
bbb
ccc
$ # command line
Eylem:
python -c 'import sys, itertools; f=open(sys.argv[1]);
lines=list(itertools.takewhile(str.isspace, f.readlines()[::-1]));
print(len(lines)); f.close()' input.txt
Çıktı:
3
https://docs.python.org/3/library/itertools.html?highlight=itertools#itertools.takewhile