Kabuk komutlarını kullanarak bir dosyanın ilk n satırını ve son satırını nasıl silerim?


31

Element_queryBir sorgunun sonucunu içeren bir dosya var :

SQL> select count (*) from element;

[Output of the query which I want to keep in my file]

SQL> spool off;

Shell komutunu kullanarak 1. satırı ve son satırı silmek istiyorum.


2
Muhtemelen bunu SQL * Plus içinde düzeltmek için en iyisi; Bir dosya oluşturmak ve daha sonra istemediğiniz şeyleri kırpmaya çalışmak yerine, SQL * Plus'a başlamak için o şeyleri oluşturmamasını söyleyebilirsiniz. Yaklaşımlardan biri docs.oracle.com/cd/A84870_01/doc/sqlplus.816/a75664/ch44.htm adresindeki "Düz Dosya Oluşturma" bölümünde açıklanmaktadır ; Başka bir yaklaşım stackoverflow.com/q/2299375/978917 adresinde anlatılmıştır .
Ruakh

Yanıtlar:


48

GNU’yu kullanma sed:

sed -i '1d;$d' Element_query

Nasıl çalışır :

  • -iseçenek dosyayı kendisi düzenler. İsterseniz bu seçeneği kaldırabilir ve çıktıyı yeni bir dosyaya veya başka bir komuta yönlendirebilirsiniz.
  • 1dilk satırı siler ( 1yalnızca ilk satırda hareket detmek, silmek için)
  • $dSon satırı siler (silmek $için yalnızca son satırda hareket detmek)

Daha ileri gidiyor:

  • Bir aralığı da silebilirsiniz. Örneğin 1,5d, ilk 5 satırı silerdi.
  • Ayrıca SQL>ifadeyi kullanmaya başlayan her satırı silebilirsiniz./^SQL> /d
  • İle her boş satırı silebilirsiniz /^$/d
  • Son olarak, herhangi bir ifadeyi noktalı virgülle ( statement1;statement2;satement3;...) ayırarak veya komut satırında ( -e 'statement1' -e 'statement 2' ...) ayrı olarak belirterek birleştirebilirsiniz.

Silmek için 3 satır ise ... o zaman 1d yerine 3d kullanmak zorundayım? En son 3. satır silmek için ... o zaman komut ne olacak?
pmaipmui

Kabuk komutlarını kullanarak 3. satırı nasıl silebilirim?
pmaipmui

@Nainita Bir aralık belirleyebilirsiniz ( 1,3dilk üç satırı siler), ancak son için biraz daha zor. Ne istediğine bağlı olarak, bunu kullanmaktan daha iyi olabilirsin: dosyada nerede olursa olsun sed -i '/^SQL> /d' Element_querybaşlayan satırları silmek SQL> .
user43791

@Nainita - rasgele kuyruk sayımları için buradaki cevabımı gör - dosyanın sonuna göre sayım satırlarını sıyırmak için iki çözüm sunar . Biri bir sedliner - bir dosyanın başından ve kuyruğundan rastgele satır sayımlarını sıyırmak için çalışacak , girdi normal bir dosya olduğu sürece, sadece iki headişlem boyunca tek bir girişi gruplamak olsa da daha iyi - bu genellikle bunu yapmanın en hızlı yolu.
mikeserv

Ben sed -i '1d' table-backup.sqlsql metin dosyasının ilk satırını silmek için kullanılır
David Thomas

8

kafa; kafa

{   head -n[num] >/dev/null
    head -n[num]
}  <infile >outfile

Yukarıdakiler ile, ilk headkomutla w / çıktının başından çıkarılacak ilk satır sayısını outfileve ikinci ile yazılacak satır sayısını belirleyebilirsiniz . Aynı zamanda bunu sed, iki giriş gerektirmesine rağmen - özellikle girdi büyük olduğunda - olduğundan daha hızlı yapar . Nerede sedkesinlikle olmalıdır olsa tercih edilebilir, durumda olduğunu <infileolduğunu değil düzenli, lseekable bu genellikle olacak çünkü - Dosya değil bu durumda amaçlanan, ancak çalışma sedtek metne süreçte tüm çıkış değişiklikleri işleyebilir.

Bir GNU ile headkullanabileceğiniz -negatif formunu [num]ikinci komuta de. Bu durumda aşağıdaki komut girişten ilk ve son satırları çıkarır:

{   head -n1 >/dev/null
    head -n-1
}  <infile >outfile

VEYA bir POSIX ile sed:

Örneğin, 20 satırlık bir girdi okuyordum ve ilk 3 ve son 7'yi çıkarmak istedim. Bunu w / ile çözmem gerekirse sed, bunu bir kuyruk tamponu ile yapardım. İlk önce on ile toplam şerit sayısı için üç ve yedi ekleyeceğim ve sonra yapacağım:

seq 20 | sed -ne:n -e '3d;N;1,10bn' -eP\;D

Bu, ilk 3 ve son 7 çizgiyi girişten çıkaran bir örnektir. Buradaki fikir, bir yığın üzerindeki desen uzayındaki giriş kuyruğundan sıyırmak istediğiniz kadar fazla satır tamponlayabilmeniz, ancak Pbunlardan ilkiyle çekilen her satır için işaretlemeniz olabilir.

  • Hatlarda 1,10 sed Pçünkü bir desen boşluk satır-satır giriş istifleme olan bu her biri için bir şey rints bçiftlik döngü.
  • 3. satırda, tüm sedyığınlar delenir - ve böylece ilk 3 satır bir baskın halinde çıktıdan çıkarılır.
  • Ne sedulaştığında $çekmek için giriş ve girişimi son hat Next bu EOF vurur ve tamamen işlem durur. Fakat o zaman desen uzayı, 14,20hiçbiri henüz Paçılmayan ve asla olmadıkları tüm satırları içerir .
  • Diğer tüm satırlarda, desen uzayında sed Psadece ilk ortaya çıkan \newline kadar işaret eder ve Dkalanlarla - veya sonraki 6 satırının girdiği yeni bir çevreye başlamadan önce aynı şeyi siler. 7. satır, Nyeni çevrimde ext komutu ile tekrar yığına eklenir .

Ve böylece, seqçıktısı (sırayla 20 numaralandırılmış 20 satırdır) , sedyalnızca aşağıdakileri yazdırır:

4
5
6
7
8
9
10
11
12
13

Giriş kuyruğundan soymak istediğiniz satır sayısı büyük olduğunda bu sorunlu hale gelir - çünkü sedperformansı, desen alanının boyutuyla doğrudan orantılıdır. Yine de, birçok durumda uygulanabilir bir çözümdür - ve POSIX sed, kırmadan önce en az 4 kb'lık işlemek için bir desen alanı belirler.


1
gnu tailda genişletilmiş destekler tail -n+<num>"satırından başlatmak anlamına sözdizimi <num>"
UloPe

4

Birkaç satırı nasıl sileceğimi cevaplamayacağım. Soruna bu şekilde saldıracağım:

grep -v '#SQL>' Element_query >outfile

Satırları saymak yerine, istemleri tanıyarak SQL komutlarını ortadan kaldırır. Bu çözüm daha sonra iki oturumdan daha fazla komut içeren SQL oturumlarının diğer çıktı dosyaları için genelleştirilebilir.


Bunu sevdim. SQL hakkında fazla bir şey bilmiyorum - ancak çıktı satırlarının başında gerçekleşen istemlerin şansı yok mu?
mikeserv

4

ed'standart metin editörü' dür ve GNU'su olmayan sistemlerde mevcut olmalıdır sed. Başlangıçta bir metin editörü olarak tasarlandı, ancak komut dosyası yazmaya çok uygun.

printf '%s\n' 1d '$d' w q | ed Element_query

1dDosyanın ilk satırını siler $d(kabuğun değişken olmadığını düşünmesi için alıntı yapılır) son satırı siler w, dosyayı yazar ve qçıkar ed. printfBurada komutları biçimlendirmek için kullanılır ed- her birinin bir yeni satır izlemesi gerekir; Elbette bunu başarmanın başka yolları da var.


3

Öndeki ve sondaki çizgileri bir dosyadan kaldırmak için birkaç yol vardır.

Sen kullanabilirsiniz awko desen eşleştirme ve çizgi sayma hem kolları olarak,

#you need to know length to skip last line, assume we have 100 lines
awk 'NR>1 && NR<100 {print $0};' < inputfile
#or
awk '/SQL/ {next}; {print $0;};' < inputfile |awk 'NR>1&& NR<10 {print $0};'

İstediğiniz grep -vçizgileri kalıba göre hariç tutmak için kullanabilirsiniz ve -Eseçeneği kullanarak birden çok kalıbı eşleştirebilirsiniz.

grep -v -E "SQL>" < inputfile > outputfile

Belirli satır sayısını kesmek için kullanabilir headvetail

lines=$((`wc -l < inputfile`-2)) #how many lines in file, less 2
head -n-1 < inputfile | head -n$lines > outputfile
#or
tail -n+2 < inputfile | head -n$lines > outputfile

vi/vimİlk ve son satırları kullanabilir ve silebilirsiniz,

vi inputfile
:1
dd
:$
dd
:w! outputfile
:x

Bir perl betiği kullanabilir, ilk satırı atlayabilir, her satırı kaydedebilir, bir sonraki satırı aldığınızda yazdırabilirsiniz.

#left as exercise for the reader :-)

1
Bunlar için headaslında boruya ihtiyacınız yok ve aslında eğer ondan uzaklaşırsanız hiç kullanmamak daha iyidir. Siz yaptığınız zaman head | head- iki işlem aynı anda çalışabilirken, ikisi de aynı veriyi pratik olarak gereksiz bir şekilde işliyorlar. Bunun yerine ne olursa { head >dump; head >save; } <inyalnızca offset tarafından atlamak - ilk ortaya 10 satır okur >dumpve ikinci okur sonraki dışarı 10 satır >save.
mikeserv

3

SQL komutlarını keserek çok daha iyi hizmet edersiniz . Bunu iki yolla yapabilirsiniz:

  1. Eğer varsa kesinlikle emin dizisi "o SQL>" yok değil çıktıda başka bir yerde meydana,

    grep -v -F 'SQL> ' < infile > outfile
  2. Eğer emin değilseniz,

    grep -v '^SQL> .*;$' < infile > outfile

İkinci versiyon daha yavaş ama daha doğru: "SQL>" ile başlayan ve ortadan kaldırılmasını istediğiniz satırları tanımlayan noktalı virgülle biten satırları yok sayacak.

Ancak, bu ekstra çıktının dosyaya başlamaması daha iyi olacaktır. Çoğu SQL sisteminin bunu yapmasının bir yolu vardır. Oracle ile fazla konuşmuyorum, ama belki bu cevap yardımcı olabilir.


3

Bir aralıktaki satırları seçebilirsiniz awk(bu kaç satır olduğunu bildiğinizi varsayar):

awk 'NR>1 && NR < 3' file

Veya Perl'de:

perl -ne 'print if $.>1 && $.<3' file

Kaç tane satır olduğunu bilmiyorsanız, bunu kullanarak anında hesaplayabilirsiniz (bunun grepboş satır saymayacağını unutmayın; grep -c '' filebunları saymak için de kullanın ):

awk -vm="$(grep -c . file2.txt)" 'NR>1 && NR<m' file2.txt

3

Bu çözümü deneyin:

tail -n +2 name_of_file | head -n-1

Özelleştirme

Kolayca n ilk satırları değişen silmek için adapte edebilir +2arasında tail;
veya değişen son n satırları silmek -1arasında head.


Bu çözüm ilk satırı yazdırırken yanlıştır.
xhienne

1
@ xhienne Üzgünüm, bir hataydı. "Tail" parametresi olarak 2 yerine 1 yazdım. Şimdi çalışıyor, teşekkürler! :)
Gabrer

1

Kullanarak awk:

< inputfile awk 'NR>1 {print r}; {r=$0}' > outputfile
  • < inputfile: İçeriğini yönlendirir inputfileiçin awkyıllardanstdin
  • > outputfile: İçeriğini yönlendirir awksitesindeki stdoutiçinoutputfile
  • NR>1: aşağıdaki işlemleri yalnızca işlenmekte olan kaydın sayısı 1'den büyükse yürütür.
  • {print r}: değişkenin içeriğini yazdırır r
  • {r=$0}: işlenmekte olan kaydın içeriğini değişkene atar r

Bu nedenle, awkbetiğin ilk yürütülmesinde , ilk eylem bloğu yürütülmez, ikinci eylem bloğu yürütülür ve kaydın içeriği değişkene atanır r; ikinci uygulamada, ilk eylemler bloğu yürütülür ve değişkenin içeriği ryazdırılır (böylece önceki kayıt basılır); Bunun, işlenen her satırın ancak birincisinin ve sonuncusunun yazdırılması etkisi vardır.


İlk satırı hariç tutmuyorsunuz. NR == 2 konumunda, depolanan ilk girdi satırını yazdırırsınız r.
xhienne
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.