İki yankı komutunun çıkışları arasında \ n nasıl kaldırılır?


13

Her satırda bir dosya adı içeren bir metin dosyası var:

111_c4l5r120.png
123_c4l4r60.png
135_c4l4r180.png
147_c4l3r60.png
15_c4l1r120.png
...

Bu şekilde dönüştürmek istiyorum:

111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15
...

bu kodu kullanarak:

#!/bin/bash
while IFS='' read -r line || [[  -n "$line"  ]]; do
   echo "$line" >> output.txt   
   echo "$line" | cut -d'_' -f 1 >> output.txt
done < "$1"

ancak sonuç şudur:

111_c4l5r120.png 
111
123_c4l4r60.png 
123
135_c4l4r180.png 
135
147_c4l3r60.png 
147
15_c4l1r120.png 
15
...

Arzu çıktısı için betiğimi nasıl değiştirmeliyim?


Google daha iyi sonuçlar bulur, örneğin bu .
Thomas Dickey

Yanıtlar:


17

Kabuğu bunun için özel bir gereksiniminiz olmadığı sürece, terdon'un cevabı daha iyi alternatifler sağlar.

Kullandığınız yana bash(komut dosyasının shebang gösterildiği gibi), kullanabilirsiniz -nyankı seçeneği:

echo -n "${line} " >> output.txt
echo "$line" | cut -d'_' -f 1 >> output.txt

Veya satırı kullanmadan işlemek için kabuk özelliklerini kullanabilirsiniz cut:

echo "${line} ${line%%_*}" >> output.txt

(her iki echosatırı da değiştirerek ).

Alternatif olarak, printfhile de yapılabilir, herhangi bir POSIX kabuğunda çalışır ve genellikle daha iyidir ( ayrıntılar için printf neden yankıdan daha iyidir? Bölümüne bakın):

printf "%s " "${line}" >> output.txt
echo "$line" | cut -d'_' -f 1 >> output.txt

veya

printf "%s %s\n" "${line}" "${line%%_*}" >> output.txt

(Kesin olarak, açıkçası /bin/sh, echo -ntaşınabilir değildir . bashBurada açıkça kullandığınız için.)


Yorumlar uzun tartışmalar için değildir; bu görüşme sohbete taşındı .
terdon

23

Kabukta böyle bir şey yapma! Gerekenden çok daha karmaşık, hatalara yatkın ve çok, çok daha yavaş. Bu tür metin manipülasyonu için tasarlanmış birçok araç vardır. Örneğin, sed(burada son GNU veya BSD uygulamalarını varsayarak -E):

$ sed -E 's/([^_]*).*/& \1/' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

Veya, herhangi biri için sed:

$ sed 's/\([^_]*\).*/& \1/' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

Perl:

$ perl -pe 's/(.+?)_.*/$& $1/' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

awk:

$ awk -F_ '{print $0,$1}' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

1
Harici araçlar daha iyi değil.
EKons

6
@ ΈρικΚωνσταντόπουλος evet onlar. Aslında birkaç büyüklük sırası daha hızlı. Kabuk bu tür şeylerde çok iyi değil. Bir kabuğun ana işi, sonuçta harici yardımcı programları başlatmaktır. OP'nin yaklaşımı ile harcanan zamanı, buradaki çözümlerden herhangi biri ile karşılaştırın. Kabuk döngüleri çok, çok yavaş. Eğer daha fazla ikna gerekiyorsa, okuma bu .
terdon

Taşınabilirlik açısından hayır. Hız açısından, evet. Ayrıca, @ StéphaneChazelas sizin takma adınız mı?
EKons

4
@ ΈρικΚωνσταντόπουλος Θα 'θελα :) Hayır, sadece iki yorum konusu ile ilgili 2 harika cevap yazmış oluyor. Taşınabilirliğe gelince, sadece * nix makinelerinin ~% 90'ı gibi bir şey üzerinde çalışacak perl yaklaşımı (küçük) istisnasıyla, üç çözüm de taşınabilir ve kabuk agnostiktir. Veya, Tamam, her zaman ekstra taşınabilirlik için sediçine yapabilirsiniz sed 's/\([^_]*\).*/& \1/' file. Nokta güvenebileceğiniz olduğunu awkve seddaha başka hemen hemen her şeyi güvenebilirsiniz daha orada olmak.
terdon

2

Buyrun:

#!/bin/bash

while IFS='' read -r line || [[  -n "$line"  ]]; do
   echo "$line" `echo "$line" | cut -d'_' -f 1` >> output.txt
#   echo "$line" | cut -d'_' -f 1 >> output.txt
done < "$1"

Çıktı:

$ rm -rf output.txt
$ ./test.sh 1.1; cat output.txt
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15
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.