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.