Sınırlandırılmış bir metin dosyasını bash içinde komut bağımsız değişkenleri olarak ayrıştırma


10

Ben böyle bölünmüş bir metin dosyası var:

field1,field2,field3 
xield1,xield2,xield3 
dield1,dield2,dield3 
gield1,gield2,gield3

Bu sütunların her biri bir programa parametre olacak ve her satır için programın çağrılmasını istiyorum

Bir döngü umuyordum, şöyle bir şey:

for $i in file
    command $field2 -x $field3 -PN -$field1 >> output
done

Bash'da böyle bir şeyi başarmanın en iyi yolu ne olurdu?


Alan sayısı sabit mi?
Joseph R.

@JosephR. evet, her zaman 3
Dean

Yanıtlar:


7
while IFS=, read xx yy zz;do
    echo $xx $yy $zz
done < input_file

Alanların sayısı sabitse bu işe yaramalıdır. echoKomutunuzu kullanmak yerine .


Teşekkürler, sadece bunu deniyordum ama sadece ilk satır için çalışıyor gibi görünüyor. Bir komut başarılı olur olmaz bir sonrakini denemez, başarısız olursa bir sonrakini olsa dener ...
Dean

Başarıyla mı yoksa başarısızlıkla mı kastediyorsun? Komutunuz ne yapıyor?
coffeMug

Çalıştırdığı komutun, "okuma" komandına erişmeden önce standart girdiyi okuduğunu tahmin ediyorum.
plugwash

4

Dahili bir whileile kullanmalısınız read:

while IFS= read -r line;do
    fields=($(printf "%s" "$line"|cut -d',' --output-delimiter=' ' -f1-))
    command "${fields[1]}" -x "${fields[2]}" ... # ${fields[1]} is field 2
done < your_file_here

Bu nasıl çalışır?

  • cutDeyim hattını alır ve belirlenen sınırlayıcı üzerine böler -d.
  • --output-delimiterAyırıcı karakteri cutbiz diziye farklı alanlarını koyabilirsiniz böylece burada bir boşluk seçmek, seçilen alan görüntülemek kullanacaktır fields.
  • Son olarak, tüm alanları (1. alandan sona) istiyoruz ve işte burada -f1-devreye giriyor.
  • Şimdi dizi değişkeninde depolanan farklı alanlara fieldssahipsiniz, sözdizimi ile istediğiniz herhangi bir alana erişebilirsiniz, ${field[number]}burada numberdizi indekslemesi Bash'te sıfır temelli olduğundan istediğiniz gerçek alan numarasından daha azdır.

Not

  • Alanlarınızdan herhangi biri boşluk içeriyorsa bu başarısız olur.

Sabit sayıda alan için

Bunun yerine 1_CR yanıtına benzer bir şey yapabilirsiniz :

while IFS= read -r line;do
    IFS=, read -r field1 field2 field3 <<-EOI
    $line
    EOI
    command "$field2" -x "$field3" ... 
done < your_file_here

Yukarıdaki, daha gürültülü gibi görünse de, sadece Bash değil, POSIX uyumlu herhangi bir kabukta da çalışmalıdır.


Sorun yaşadığım dosyada okumak değil, satırı sütunlara ayırıyor.
Dean

@Dean Evet, üzgünüm. Dikkat etmiyordum. Şimdi üzerinde çalışıyorum.
Joseph R.

@Dean Lütfen güncellenmiş cevaba bakınız. Kısaca bir açıklama ekleyeceğim.
Joseph R.

. @JosephR, o ayarlayarak yarma için harici araçlar kullanarak önlemek mümkündür IFSuygun bir değere readçağırma
Iruvar

@ 1_CR Biliyorum, teşekkürler. Sadece buna başlamıştım :)
Joseph R.

1

Sen alabilirsiniz readüzerinde bir diziye Her satırı bölmek ,ayarlayarak IFSuygun.

while IFS=, read -r -a input; do
 printf "%s\n" "${input[0]}" "${input[1]}"
done < input.txt

Yukarıdaki örnekte, her dizi öğesine 0'dan başlayarak dizinini kullanarak erişebilirsiniz.


1

Bu awktek astar istediğinizi yapacak:

awk -F, '{cmd="echo " $2 " -x " $3 " -PN " $1 ">> output";  system(cmd)}' f.txt

echoKomutunuzla ve f.txtyineleme yapmak istediğiniz dosyayla değiştirin .

Kısa açıklama: sınırlayıcı olarak -F,ayarlanacaktır ,. cmdkomutu oluşturur ve komutu system(cmd)çağırır.


1

gnu sed de kullanılabilir.

sed infile -e 's!^\([^,]*\),\([^,]*\),\([^,]*\)$!command \1 -x \2 -PN \3!e' >> output

s komutunun e seçeneğinin kullanıldığına dikkat edin

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.