Linux'ta bir dosyanın son sütunu nasıl silinir


25

Sütun numarasının ne olduğunu bilmiyorum, bir txt dosyasının son sütununu silmek istiyorum. Bunu nasıl yapabilirim?

Örnek:

Giriş:

1223 1234 1323 ... 2222 123
1233 1234 1233 ... 3444 125
0000 5553 3455 ... 2334 222

Ve çıktımın olmasını istiyorum:

1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

Bunu yapmanın pek çok yolu var ... lütfen bir örnek ve ondan beklenen çıktınızı ekleyin ..
heemayl

@heemayl ok Yaptım
zara

Teşekkürler .. sütunlar sekmesi ayrılmış veya boşluk ayrılmış mı?
heemayl

@heemayl alan sınırlayıcıdır
zara

Yanıtlar:


43

İle awk:

awk 'NF{NF-=1};1' <in >out

veya:

awk 'NF{NF--};1' <in >out

veya:

awk 'NF{--NF};1' <in >out

Bu vudu çiçeği gibi gözükse de işe yarıyor. Bu awk komutlarının her birinde üç bölüm vardır.

Birincisi NF, ikinci bölüm için bir önkoşuldur. NFbir satırdaki alan sayısını içeren bir değişkendir. AWK’de, 0 değil veya boş bir dize varsa, şeyler doğrudur "". Dolayısıyla, ikinci kısım ( NFazaltılan yerde ) sadece NF0 değilse gerçekleşir .

İkinci parça (ya NF-=1 NF--da --NF) sadece birini NFdeğişkenden çıkartıyor. Bu, son alanın yazdırılmasını önler, çünkü bir alanı değiştirdiğinizde (bu durumda son alanı kaldırarak), awkyeniden yapılandırın $0, varsayılan olarak boşlukla ayrılmış tüm alanları birleştirin. $0artık son alanı içermiyordu.

Son kısım 1. Büyülü değil, sadece bir ifade olarak kullanılıyor true. Bir awkifade, ilişkili bir işlem yapmadan true olarak değerlendirilirse, awkvarsayılan eylem şöyledir print $0.


@Joao: Ah, teşekkürler, unuttum --. Şu anda bir not, ;1POSIX uyumlu için ihtiyacınız var .
cuonglm

İlk içgüdüm bir for döngüsü kullanmak olurdu, ama bu çok daha özlü ve zekice.
Sergiy Kolodyazhnyy

5
Varsayılan olmayan bir sınırlayıcı kullanıyorsanız, bazı değişiklikler yapmanız gerekeceğini belirtmekte fayda var. ,Sizin sınırlayıcınız olduğunu farz edersiniz:awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out
Bay Llama

1
NF'yi azaltmanın etkisi, POSIX'in tanımsız davranışıdır - çalıştırmakta olduğunuz awk'a bağlı olarak farklı çıktılar alırsınız. Bazı awks istediğiniz alanı kaldırır, bazıları hiçbir şey yapmaz ve diğerleri sözdizimi hatası veya başka bir şey bildirebilir.
Ed Morton

16

grepPCRE ile kullanma :

$ grep -Po '.*(?=\s+[^\s]+$)' file.txt 
1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

GNU’yu kullanma sed:

$ sed -r 's/(.*)\s+[^\s]+$/\1/' file.txt 
1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

1
@ramin Sure .. lütfen yeni bir soru olarak sorabilir misiniz (bu site böyle çalışır) :)
heemayl

@ ramin Size zaman kısıtlaması veya herhangi bir uyarı veriyor mu?
heemayl

Bunun standart bir soru olmadığını söylüyor!
zara

@ramin Tamam..bana bir yönetici ile iletişime geçin, bu konuda size yardımcı olabilirler .. bbw Sorunuzla ilgili herhangi bir eski KG'yi kontrol ettiniz mi? soru zaten sorulan ve cevaplanan bir olasılık ..
heemayl

3
" Linux'ta bir dosya adını nasıl yeniden adlandırabilirim " gibi süper basit sorular sormayın . Google kullan.
Christoffer Hammarström

11

Perl kullanımı:

perl -lane '$,=" ";pop(@F);print(@F)' in

rev+ Kullanarak cut:

rev in | cut -d ' ' -f 2- | rev

5

GNU sed kullanma:

sed -r 's/\s+\S+$//' input.txt

Daha genel olarak, bu OSX’te BSD sed ve GNU sed’de çalışır:

sed 's/[[:space:]]\{1,\}[^[:space:]]\{1,\}$//' input.txt

1

Sınırlayıcı her zaman tek bir karakter ise (iki veya daha fazla ardışık sınırlayıcı boş alanları belirler), headgirdi dosyanızdaki ilk satır olabilir , sınırlayıcıları sayın ( nsınırlayıcılar alan sayısıdır n+1), ardından st alanından cutyazdırmak için kullanın 1kadar ninci alan (ikinci sonuncusu), mesela sekme ile ayrılmış giriş ile:

n=$(head -n 1 infile | tr -dc \\t | tr \\t \\n | wc -l)
cut -f1-$n infile > outfile

veya örneğin bir csv dosyasıyla:

n=$(head -n 1 infile | tr -dc , | tr , \\n | wc -l)
cut -d, -f1-$n infile > outfile

Zamanım varsa ancak çok büyük girdiyle bazı kriterleri çalıştıracağım, bu çözümün ilk satırda minimum işlem yapması nedeniyle regex kullanan diğer çözümlerden daha hızlı olması gerektiğini düşünüyorum. Alanlar ve daha sonra cutbu iş için optimize edilmiş olan kullanımlar.


1

Taşınabilir olarak şunlardan birini kullanabilirsiniz:

sed 's/[[:space:]]*[^[:space:]]*$//' file

awk '{sub(/[[:space:]]*[^[:space:]]*$/,"")}1' file

0

Vim kullanarak:

Dosyayı vim'de aç

vim <filename> 

İmlecin başka bir yere yerleştirilmesi durumunda ilk satıra gidin.

gg

"Q" adlı bir makro oluşturun qqgeçerli sıranın arkasına gider, $ardından son uzaya geri gider F(literal ALAN ardından sermaye F) daha sonra hattın sonuna kadar geçerli konumdan silmek Dsonraki satıra inmek jve ile makro kaydını durdur q.

qq$F Djq

Şimdi @qher satır için makromuzu tekrarlayabiliriz .
Ayrıca @@son makroyu tekrarlamak için basabiliriz veya daha kolay:

99@q

Makroyu 99 kez tekrarlamak için
Not: Numara, satırlarla tam olarak eşleşmemelidir.


0

Benzer bir sorunu olan ancak farklı alan ayırıcıları olan kişiler için bu awkyöntem alan ayırıcıyı doğru koruyacaktır:

$ cat file 
foo.bar.baz
baz.bar.foo
$ awk -F'.' 'sub(FS $NF,x)' file
foo.bar
baz.bar
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.