Bir dosyanın farklı satırlarını farklı değişkenlere nasıl okursunuz?


14

Bir metin dosyasının farklı satırlarını farklı değişkenlere okumak istiyorum. Örneğin

input.txt:

line1 foo foobar bar
line2 bar
line3 foo
line4 foobar bar

Bu sonuç, değişkenleri saklanabilir istiyorum var1, var2, var3ve var4bu tür

var1=line1 foo foobar bar
var2=line2 bar

ve bunun gibi.

Birisi bana bunun nasıl yapıldığını söyleyebilir mi? evalFor döngüsünde kullanmaya çalıştım . Çalışmıyor gibi görünüyor.



3
Bu kötü bir yaklaşım. Temelde ayarlanan değişkenlere tek nedeni olduğu için onlarla bir şeyler yapmak, ve özellikle araçların geniş bir dizi vardır çünkü tasarlanmış bir dosyada metnin her satırında ve Yapmak (Awk Sed, grep, cutet. Al.), sadece yapmanız gerekenleri yapmak çok daha iyi . Kabuk betiğinde mikro yönetim yapmayın; işi yapmak için araçları düzenlemek.
Joker

Yanıtlar:


20

Yapacaksın:

unset -v line1 line2
{ IFS= read -r line1 && IFS= read -r line2; } < input.txt

Veya:

{ line1=$(line) && line2=$(line); } < input.txt

( linenadiren yerleşik olduğu için daha az verimlidir ve çoğu mermi komut ikamesi için çatallamaya ihtiyaç duyar. lineartık standart bir komut değildir).

Bir döngü kullanmak için:

unset -v line1 line2 line3
for var in line1 line2 line3; do
  IFS= read -r "$var" || break
done < input.txt

Veya değişkenlerin adlarını otomatik olarak şu şekilde tanımlamak için line<++n>:

n=1; while IFS= read -r "line$n"; do
  n=$((n + 1))
done < input.txt

bashDizi değişkenlerini ve readarraysatırları bir diziye okumak için bir yerleşkeyi destekleyen unutmayın :

readarray -t line < input.txt

Bununla birlikte, diğer kabukların aksine, bashdizi indeksleri 0 değil 1'den (devralınan ksh) başlar, bu nedenle ilk satırın içinde olmayacağını ${line[0]}unutmayın ${line[1]}( @Costas'ın gösterdiği gibi , readarray(aka mapfile) indice'deki değerleri yazmaya başlayabilirsiniz 1 ( bashdiziler, diğer kabukların seyrek diziler olmasının aksine ) ile -O 1).

Ayrıca bkz: "IFS = okuma -r satırı" nı anlama?


12

Bu tür görev (ler) için dizi kullanmayı öneririm

mapfile -t -O 1 var <input.txt

böylece her satırı gireceksiniz ${var[1]}, ${var[2]}vb.


Bu tek astar çok iyi çalışıyor. Sorun benim için çözüldü.
Matt Zabojnik

0

Bu tam olarak istediğin şey değil, ama ihtiyaçlarınız için işe yarayabilir. Verileri Awk ile serileştirebilirsiniz. $ 1 değeriniz geçerli bir değişken adı değilse, bunun bozulacağını unutmayın:

awk '
function quote(str,   d, m, x, y, z) {
  d = "\47"; m = split(str, x, d)
  for (y in x) z = z d x[y] (y < m ? d "\\" d : d)
  return z
}
{
  print $1 "=" quote($0)
}
' input.txt > /tmp/input.sh
. /tmp/input.sh

Sonuç:

$ echo "$line1"
line1 foo foobar bar

Bu gerçekten garip bir kod! Tüm girdi dosyasını daha sonra kaynakladığınız bir bash betiğine dönüştürmek için awk kullandığınız anlaşılıyor. Alıntı () 'ın ne yaptığına dair belirsiz bir fikrim var. Daha açıklayıcı değişken adları yardımcı olacaktır. Biraz daha açıklayabilir misiniz?
Joe
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.