Linux за българи: Форуми

Програмиране => Общ форум => Темата е започната от: PhrozenCrew в Nov 16, 2009, 11:15



Титла: bash - Принтване на 2 променливи от масив при цикъл
Публикувано от: PhrozenCrew в Nov 16, 2009, 11:15
Здравейте,

Опитвам се да направя простичка текстова база данни, но нещо не мога да се сетя как да изкам втори или трети елемент от масива. Ето примера:
файл дб - users.txt
Ime1:Vor name 1:addres 1
Ime2:Vor name 2:addres 2
Ime3:Vor name 3:addres 3
Ime4:Vor name 4:addres 4

Кода с който изваждам имената

USERS=users.txt
n=1

for name in $(awk 'BEGIN{FS=":"}{print $1}' < "$USERS" )
do
  echo "USER $n = $name"
  let "n += 1"
done

Желаниеето ми е на този ред:
echo "USER $n = $name"
да мога да добавя $addres.
Предварително благодаря за всяка идея!


Титла: Re: bash - Принтване на 2 променливи от масив при цикъл
Публикувано от: ntrance в Nov 16, 2009, 11:27
Нещо не мога да го разбера това , я дай един пример от това по горе  какъв искаш да ти бъде резулатата .


Титла: Re: bash - Принтване на 2 променливи от масив при цикъл
Публикувано от: radoulov в Nov 16, 2009, 12:01
Код:
j=0

while IFS=: read n sn a; do
  printf 'user %d = %s, address = %s\n' \
    $((++j)) "$n" "$a"
done < users.txt
   

$((++j)) изисква bash >= 3 ако не се лъжа.
Ако ти дава грешка можеш да използваш:

Код:
$((j+=1))


Титла: Re: bash - Принтване на 2 променливи от масив при цикъл
Публикувано от: neter в Nov 16, 2009, 12:19
Друго решение е с 'cut'. Ако във for цикъла на променливата $name задаваме стойност целият ред, то можем да получим това
Код
GeSHi (Bash):
  1. name='Ime1:Vor name 1:addres 1'
  2. edno=`echo $name | cut -d':' -f1`
  3. dve=`echo $name | cut -d':' -f2`
  4. tri=`echo $name | cut -d':' -f3`
На променливите $edno, $dve и $tri ще се присвоят стойности съответно "Ime1", "Vor name 1" и "address 1" ;)


Титла: Re: bash - Принтване на 2 променливи от масив при цикъл
Публикувано от: PhrozenCrew в Nov 16, 2009, 12:34
Код:
j=0

while IFS=: read n sn a; do
  printf 'user %d = %s, address = %s\n' \
    $((++j)) "$n" "$a"
done < users.txt
   

$((++j)) изисква bash >= 3 ако не се лъжа.
Ако ти дава грешка можеш да използваш:

Код:
$((j+=1))
Много интересен код! Благодаря ти, radoulov!
Версията ми е 3.2-1 и всичко е ОК. Помислих си да ползвам IFS, обаче нямам достатъчно опит.
Може ли да попитам нещо за цикъла while:
while IFS=: read n sn a
на това отговарят %d, %s и %s в същата последователност, нали?
Ако е така, значи научих още нещо за баш :)
Сега ще пробвам и с cut.
Благодаря ви пичове!


Титла: Re: bash - Принтване на 2 променливи от масив при цикъл
Публикувано от: radoulov в Nov 16, 2009, 13:09
Цитат
[...]Може ли да попитам нещо за цикъла while:
while IFS=: read n sn a
на това отговарят %d, %s и %s в същата последователност, нали?

Ако разбирам правилно въпроса - не: %d форматира и извежда променливата j,
а sn в случая не се извежда от printf.







Титла: Re: bash - Принтване на 2 променливи от масив при цикъл
Публикувано от: PhrozenCrew в Nov 16, 2009, 13:46
Вярно! Ами sn тогава какво прави?
Извинявам се за глупавите въпроси, но не можах сам да намеря логиката.

ПСМ Ето и един много лаишки код с cut:
oldIFS=${IFS} # Zapazvane na tekushtia separator
IFS=$'\n' # nov separator za krai na liniata
for line in $(cat users.txt); do
   echo "USER: "$(echo $line | cut -d":" -f1)"   ADDRES: "$(echo $line | cut -d":" -f3);
done
IFS=${oldIFS} # vrystame defoltnia separator
--
Странно ми е, че ако ползвам:
while read line; do echo $line; done <users.txt
ми се губи един ред - последният?! Ако и това някой успее да ми го обясни работата отива към черпушка :)


Титла: Re: bash - Принтване на 2 променливи от масив при цикъл
Публикувано от: radoulov в Nov 16, 2009, 14:05
Цитат
Вярно! Ами sn тогава какво прави?
Извинявам се за глупавите въпроси, но не можах сам да намеря логиката.

Позволява да достигнеш до данните за address.
Може би така ще е по-ясно:

Код:
zsh-4.3.10[t]% while IFS=: read n sn a; do
  printf 'n is |%s|, sn is |%s|, a is |%s|\n' \
  "$n" "$sn" "$a"
done < users.txt 
n is |Ime1|, sn is |Vor name 1|, a is |addres 1|
n is |Ime2|, sn is |Vor name 2|, a is |addres 2|
n is |Ime3|, sn is |Vor name 3|, a is |addres 3|
n is |Ime4|, sn is |Vor name 4|, a is |addres 4|


Титла: Re: bash - Принтване на 2 променливи от масив при цикъл
Публикувано от: radoulov в Nov 16, 2009, 14:13
Цитат
Странно ми е, че ако ползвам:
while read line; do echo $line; done <users.txt
ми се губи един ред - последният?![...]

Пробвй да конвертираш фила с dos2unix :)


Титла: Re: bash - Принтване на 2 променливи от масив при цикъл
Публикувано от: PhrozenCrew в Nov 16, 2009, 14:18
Еее-е-е, браво! Задаваш си списък с променливите. Супер полезно ми е това, което си написал!
Значи мога да използвам тази възможност както например в perl или php:
list($n, $sn, $a) = preg_split(/:/,$line)
...

Пробвах с dos2unix, но явно средата, до която имам достъп в момента не може да работи киоректно. Бачкам със CygWin под WinXPSP3. А и версията ми е старичка. Довечера в къщи ще пробвам пак.

Благодаря отново!