Portál AbcLinuxu, 9. června 2024 16:20


Dotaz: Seznam/pole (nebo tak něco) v sh

Jardík avatar 1.4.2014 16:10 Jardík | skóre: 40 | blog: jarda_bloguje
Seznam/pole (nebo tak něco) v sh
Přečteno: 189×
Odpovědět | Admin
Potřeboval bych vytvořit něco jako seznam či pole v sh (bude to busyboxí ash nebo dash, bash ne).

Např. když mám skript, který vypisuje argumenty
for i in $*; do
  echo "$i"
done
A zavolám ho:
$ myscript meow meow2 "meow with space"
meow
meow2
meow
with
space
Stejně je to když použiju $@ místo $*. Když to ale dám do uvozovek jako "$*" a "$@", tak dostávám:
# for i in "$*"; do echo "$i"; done
meow meow2 meow with space

# for i in "$@"; do echo "$i"; done
meow
meow2
meow with space
Poslední příklad mi tedy dává, co potřebuju, v případě argumentů předaných skriptu. Co teď ale potřebuju je něco podobného s proměnnou místo argumentů. Následující nefunguje
myvar="meow meow2 \"meow with space\""

# for i in ${myvar}; do echo "$i"; done
meow
meow2
"meow
with
space"

# for i in "${myvar}"; do echo "$i"; done
meow meow2 "meow with space"
Co potřebuju je výstup
meow
meow2
meow with space
Věřím v jednoho Boha.
Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

1.4.2014 16:46 potato
Rozbalit Rozbalit vše Re: Seznam/pole (nebo tak něco) v sh
Odpovědět | | Sbalit | Link | Blokovat | Admin
Posixový shell nemá pole (kromě argumentů) ani nepřímé reference. Viděl bych tyto možnosti:

(a) Využít toho, že je k disposici jen jedno pole, ale není globální a formulovat celý kód tak, že se pole předávají dokola jako argumenty funkcí.

(b) Narvat to do jedné proměnné, použít delimitery a pokaždé dělat explicitní split-unescape-escape-join cyklus.

(c) Zatnout zuby a použít eval.

(d) Ukládat data jinak (do souborů, etc.).

(e) Nepsat RDBMS v dashi...
Jardík avatar 1.4.2014 16:48 Jardík | skóre: 40 | blog: jarda_bloguje
Rozbalit Rozbalit vše Re: Seznam/pole (nebo tak něco) v sh
Odpovědět | | Sbalit | Link | Blokovat | Admin
Tek jsem se dopracoval zatím k něčemu takému:
# embeded newline
myvar="meow
meow2
meow with space"

SAVEIFS="${IFS}"

# split on newline
IFS=$'\n'
a=1

for i in ${myvar}; do
  echo "arg${a}: ${i}"
  a=$((a+1))
done

IFS="${SAVEIFS}"
Tedy mám "jakési" pole, kde jsou položky rozděleni znakem nového řádku. Problém je, že znak nového řádku se může vyskytovat třeba ve jménu souboru (asi zřídka, ale může), takže by to chtělo jiný oddělovač. Bohužel nula (tj. jediný znak, který není v cestě souboru) jaksi v sh nefunguje :-(
Věřím v jednoho Boha.
Jardík avatar 1.4.2014 19:36 Jardík | skóre: 40 | blog: jarda_bloguje
Rozbalit Rozbalit vše Re: Seznam/pole (nebo tak něco) v sh
Hmm, tak na webu ubuntu tvrdí, že $'\n' je bashismus. V busyboxím ash mi to funguje, ale chtěl bych to mít portabilní (česky?). Zkusil jsem tedy jejich IFS="$(printf '\n')", jenže to mi novou řádku ukradne a do proměnné neuloží, ačkoliv samotný printf '\n' ji produkuje.
Věřím v jednoho Boha.
1.4.2014 20:33 potato
Rozbalit Rozbalit vše Re: Seznam/pole (nebo tak něco) v sh
Protože `` a $() pojídají koncové prázdné řádky. Nejspíš je to POSIX a tradice, nechce se mi to teď dohledávat. Získat z command substitution pouze konec řádku tedy nejde, musíš za něj v printf něco přidat, aby nebyl odstraněn, pak to zase zlikvidovat.

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.