Van egy számozott listám, melyet egy tömbbe rakok.
A tömb végén meghatároztam az utolsó számot.
max_number=$(( index - 1 ))
A lista:
01 foo
02 foo
...
89 foo
A bash szkript megkér hogy válasszak egy számot a listából, majd elemzi a választott számot.
read -r choice
number_check=$(echo "${choice}" | grep -E '^[0-9]{2}|0')
A 0-ra szükségem van, viszont a többi egyjegyű számok nem kellenek. mivel a lista is kétjegyű. Ezért a regex.
Így két legyet ütök egy csapásra, Ha betűt adok meg, nem fogadja el.
Viszont van egy ilyen ellenőrző is:
if (( choice > max_number )); then
Lefut ugyan de hibát dob. Ezért elrejtem a hibaüzenetet. Bár jó lenne megoldani.
if (( choice > max_number )) >/dev/null 2>&1; then
S itt vannak a gondok.
Próbálkoztam ezzel is:
if [ ${choice} -gt ${max_number} ]; then
de a 08, 09 oktális decimális keverés miatt hibát dob, amennyiben a 08 vagy a 09-es kerül kiválasztásra.
read -r choice
number_check=$(echo "${choice}" | grep -E '^[0-9]{2}|0')
if [ "${number_check}" != "" ]; then
# if (( choice > max_number )) >/dev/null 2>&1; then
if (( choice > max_number )); then
clear
else
if [ "${choice}" = "0" ]; then
clear
exit
else
minden rendben
fi
fi
else
clear
fi
- 654 megtekintés
Hozzászólások
"if [ ${choice} -gt ${max_number} ]; then
de a 08, 09 oktális decimális keverés miatt hibát dob, amennyiben a 08 vagy a 09-es kerül kiválasztásra."
Kolumbusz tojása: if [ 1${choice} -gt 1${max_number} ]; then
- A hozzászóláshoz be kell jelentkezni
Ha "1" helyett "10#" amit eléfűzöl, akkor a kód olvashatóbb (pontosan azt írod le, amire gondolsz, nevezetesen hogy 10-es számrendszerben értendő; nem kell tippelgetni hogy vajon mire gondolt a költő) és robusztusabb (működik akkor is, ha nem azonos hosszúak a számok).
IMHO megvan a helye a Kolumbusz tojása típusú megoldásoknak is, de nem ott, ahol a rendes megoldás semmivel sem bonyolultabb.
- A hozzászóláshoz be kell jelentkezni
(Off, mindig elszörnyedek, hogy shellben milyen problémákra mi a rendes megoldás)
- A hozzászóláshoz be kell jelentkezni
Mondjuk nekem egy ilyen script nem dob hibát:
for i in $(seq -w 5 10); do echo $i; if [ ${i} -gt 6 ] ; then echo nagyobb; fi; done
de ha berakok egy echo $((i)) -t, akkor az már igen...
Shell: GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)
- A hozzászóláshoz be kell jelentkezni
Mutasd már meg, hogy hol nem jó a $((i)) ?
- A hozzászóláshoz be kell jelentkezni
[kroozo@superior tmp]$ cat t1.sh
#!/bin/bash
for i in $(seq -w 5 10); do echo $i; if [ ${i} -gt 6 ] ; then echo nagyobb; fi; done
[kroozo@superior tmp]$ ./t1.sh
05
06
07
nagyobb
08
nagyobb
09
nagyobb
10
nagyobb
[kroozo@superior tmp]$ cat t2.sh
#!/bin/bash
for i in $(seq -w 5 10); do echo $((i)); if [ ${i} -gt 6 ] ; then echo nagyobb; fi; done
[kroozo@superior tmp]$ ./t2.sh
5
6
7
nagyobb
./t2.sh: line 3: 08: value too great for base (error token is "08")
[kroozo@superior tmp]$ bash --version
GNU bash, version 5.2.15(1)-release (x86_64-redhat-linux-gnu)
- A hozzászóláshoz be kell jelentkezni
Jó, így már értem, és igaza is van, hisz a $(( .. )) kiértékel egy aritmetikai kifejezést. Márpedig a nyolcas számrendszerben 0..7 számjegyek állhatnak 8 és 9 nem annyira :-)
- A hozzászóláshoz be kell jelentkezni
Azt mondjuk nem tudom, hogy ez hogy jött az én kommentemre, csak beleírtam :)
- A hozzászóláshoz be kell jelentkezni
Zellertől megkérdeztem, hogy hol ad hibát a $((i)). Erre krozoo adott 2 scriptet, amiben megmutatta, hol rossz. Én megmagyaráztam, miért rossz. Erre rákérdezni, hogy ez hogy kerül ide - no itt én elvesztem.
- A hozzászóláshoz be kell jelentkezni
kroozo azt nem értette, hogy zeller "Mondjuk nekem egy ilyen script nem dob hibát:" kommentje mit keresett az ő off commentje alatt egyáltalán :)
- A hozzászóláshoz be kell jelentkezni
Igen. Ehhez hasonló lett a megoldás. A 10#-ről tudtam, ki is próbáltam, de csak a choice elé tettem be. Nyilván ezért is nem működött.
A jó megoldás if [[ 10#${choice} -gt 10#${max_number} ]]; then
Köszi mindenkinek.
- A hozzászóláshoz be kell jelentkezni
Szerintem egyszerűbb lenne case-zel vizsgálni az inputot, tud regexet, így az if előtti grep sem kell, az sem probléma ha üres vagy nincs szám.
"Sose a gép a hülye."
- A hozzászóláshoz be kell jelentkezni
"case-zel vizsgálni az inputot, tud regexet"
Nem, a shell nem tud regexp-et, hanem pattern-t tud (amit a fákjlnév megadásánál lehet használni). Pontosabban ma már a shell is tud regexp-et, de amennyire tudom, egyedül a [[ nevű ]] parancsban, ha a =~ operátort használod. De a case-ben nem.
- A hozzászóláshoz be kell jelentkezni
ez?
#!/bin/bash
case $1 in
[123456789])
echo szam
;;
[abc])
echo betu
;;
0)
echo nulla
;;
"")
echo semmi
;;
*)
echo default
;;
esac
"Sose a gép a hülye."
- A hozzászóláshoz be kell jelentkezni
Ez pontosan az a pattern, amit írtam. Mi sem bizonyítja jobban, mint a legutolsó ág * mintája. Regexp esetén ugyanis a * előtt kell valaminek állnia, és a * előtt álló "izé" 0, 1, 2, vagy többszöri előfordulását jelenti. Pl: [a-z]* - tetszőleges számú (0 is lehet) kisbetű. [0-9]* - számjegyek sorozata. Míg a patternként a * önmagában azt jelenti, hogy bármilyen hosszúságban bármi. Ha azt írom a*b, akkor ha ez regexp, akkor 0 vagy több kis a, amit egy db. kis b követ, azaz extrém esetben : b, vagy ab, aab, aaab, ...., aaaaaaaab. De az aaaaabbbb -ből csak az első b-ig jelenti a mintát. (*) Ha ugyanez patternként van értve, akkor kis a és kis b, amik között BÁRMI lehet: ab, aXb, aaaaaaXYZ123456b, sőt aaaabbbbbbbb, és az összes b-t is jelenti.
Azt elismerem, hogy kurva zavaró, hogy a [...] és a * mind pattern-ben, mind regexp-ben szerepelhet, de nem egészen ugyanazt jelentik. Shell-ben (és a fájlnév megadás utáni leggyakoribb előfordulás a "case" parancs) patterneket lehet használni. Egy csomó egyéb szoftvernél meg regexpeket - amik teljesen másként működnek.
(*) a linuxos grep-nél ugye van, hogy színekkel kiemeli, hogy mi az, amire a minta (regexp) illeszkedik. Így lehet ellenőrizni ezt, amit mondtam az aaabbbb és az a*b kapcsán.
- A hozzászóláshoz be kell jelentkezni
Ezt hivjak "glob"-nak, lasd: https://en.wikipedia.org/wiki/Glob_(programming)
- A hozzászóláshoz be kell jelentkezni
Teljesen igazad van, azért használtam a pattern kifejezést, mert a bash (meg az egyéb shellek - ksh93, yash) manuálja ezzel a névvel hivatkozik a globbingra.
- A hozzászóláshoz be kell jelentkezni
Továbbmenve erre a problémára van a select bash-ban: https://linuxize.com/post/bash-select/
De én még mindig véreset hányok, ha shell scripthez kell nyúlnom.
- A hozzászóláshoz be kell jelentkezni
Nekem is a select volt az első gondolatom, de a select maga generálja a számozott listát, itt meg eleve van egy (láthatóan máshogy) számozott lista.
Én pedig mindig örülök, amikor rájövök, hogy a shell script még mindig mennyi mindenre jó - igaz nem árt hozzá a nyelvet jól ismerni, és a megfelelő eszközeit használni a script megírásakor. (Tipikus példa a tipikus linuxizm / bashizm: for i in `seq 1 100` - az ilyesmire a while / until ciklus való, de ha valaki mindenáron for-t akar, akkor írjon for i in {1..100} -at.)
- A hozzászóláshoz be kell jelentkezni
1. Ne generálja magának a számokat, teljesen felesleges.
2. Hát igen, már ha lenne nyelv, csak az épp nincs :P A dolgok nagy részét a rendszeren rendelkezésre álló parancsokból kell kisakkozni (amik vagy telepítve vannak, vagy nem), amikből a GNU implementáció elég sokszor eltér a *BSD implementációtól (embedded/egyéb rendszerekről nem is beszélve). Típusok sem igazán vannak, általában a szövegeket kell parse-olni stdout-ról (ha épp nem csúszik át stderr-re), viszont regex támogatás az nincs. De egyébként a tömbök is csak bash 3(?)-tól vannak, asszociatív tömbök csak valami külső paranccsal...
- A hozzászóláshoz be kell jelentkezni
1.
"Van egy számozott listám".
Nekem ebból az jön le, hogy ez valahonnan máshonnan van
2.
Érteni értem, de pont azt mondom, hogy ismerni kell a rendszert, és úgy lehet - igen szovegmatató eszközökkel - eredményt elérni. A GNU vs *BSD implementációk problémakörét pont jól lefedi a POSIX, 35-40 éve ugatom, hogy arra kéne lőni. Nem tudom mióta van a bash-ban tömb, a Korn-shell aminek ksh88 nevű verziója már k régen elavult, már' 88-ban tudta, szóval az nem komoly probléma. A ksh93-ban pedig - igen., '93-ban - már volt asszociatív tömb :-) Ráadásul az awk - ami eléggé alap UNIX / POSIX eszköz, a 77-es verziójában tudtommal már szintén tudta, de a 88-as már garantáltan. Azaz teljesen igaza volt Larry Wall-nak, aki a "van awk 2 perl, meg sed 2 perl, miért nincs shell 2 perl" kérdésre azt válaszolta, hogy a shell-scriptek legtöbbször egy kis sed / cut / cat / tr / join, stb összeragasztására jók - nos ezt jelenti a shell program írása. Más kérdés, hogy ha az ember hajlandó megtanulni a (z igenis létező) nyelv eszköztárát, sok esetben fentieket nem feltétlenül (de jó pár esetben) 100%-ban hanyagolhatják. Akinek meg nem tetszik, tanulja meg az AWK-ot, "perl-t, vagy a ma divatos scriptnyelvek bármelyikét - de legalább a shell *alapjait* tanulja meg tisztességesen. De amíg a többség már az aposztróf vs idézőjel dolgot nem képes megtanulni, vagy hogy "minden változóhivatkozást idézőjelek közé zárunk (kivéve azt a 2 esetet amikor pont nem)" - no addig ne csodálkozzunk azon, hogy szar shell-scriptek ömlenek mindenhonnan. Szóval aki nem ismeri, az undorodhat tőle, de az ő szava szerintem keveset nyom a latban.
(A powershell jobb?)
- A hozzászóláshoz be kell jelentkezni
"kivéve azt a 2 esetet amikor pont nem" - taníts, mester :-) Lehet, hogy tudom, csak nem tudom, hogy tudom :)
A powershell van, amiben jobb. A nem bájtok sorozata, hanem objektum "közlekedik" a csőben sokszor egyszerűsíti az életet (másjor meg nem...), de ahogy mondani szoktam, feladathoz az eszközt.
- A hozzászóláshoz be kell jelentkezni
1.
a V változóban gyüjtesz dolgokat (V="$V x" stílusban), majd a benne levő szavakat szeretnéd külön-külön kezelni:
for i in $V ; do .. done
Itt nagyon rossz lenne a "$V" forma.
2.
if Z ; then
CMD_X="commandX --nondefoption"
else
CMD_X="cmdX --compat"
fi
$CMD_X param1 param2
Ha a futtatási sorban idézőjelbe teszed, akkor lesz meglepetés, hogy miért van c-n-f a 'cmdX --compat' nevű parancsra. (A shell hibaüzenetben persze nem idézőjelek / aposztrófok közt írja ki.) Ezt a formát nagyon régóta alkalmazzák az egymással csak kicsit kompatibilis rendszereken futtatható kódok írására.
- A hozzászóláshoz be kell jelentkezni
Köszönöm - mindkettő a "nem tudom, hogy tudom" kategória :-)
- A hozzászóláshoz be kell jelentkezni
Ez azért várható volt.
- A hozzászóláshoz be kell jelentkezni
Nem ismertem a select parancsot. Kipróbáltam, és nem rossz. Kérdés hogy lehet-e valahogy színezni az outputot. Külön a számokat...
- A hozzászóláshoz be kell jelentkezni
Értem, hogy megvan a megoldás, de meg tudnád mutatni azt, ahol az a if (( .. )) hibát dob? Meg pl. azt, hogy mi a hozzá tartozó input - amitől hibaüzenetet generál.. Csak mert szerintem pl. már ez se jó:
number_check=$(echo "${choice}" | grep -E '^[0-9]{2}|0')
Ha a grep minta végére raknál egy $-jelet, akkor még csak érteném, de így 12v -t szó nélkül benyeli - majd ez után tényleg kapok egy hibát. Vagy ha a grep-nek odaadnád a -o opciót, hogy csak a mintára illeszkedő eredményt írja ki, ne a teljes sort, ahol van illeszkedés.
- A hozzászóláshoz be kell jelentkezni
12v. Húú. Erre nem is gondoltam. Most megfogtál.
- A hozzászóláshoz be kell jelentkezni
A grep megoldás is jó,( bár nem a legszebb). Viszont ha maradsz regex vonalon, akkor ez csak a számokat hozza ki.
Mivel nem volt tiszta, hogy a 0[1-9]-re is akarsz-e egyezést, ezért ez most az alábbi számokra mutat egyezést.
0, 1-9,10 felett
Nem fog egyezni a 00-val és a 0[1-9]-el.
Remélem jól értettem a kérdést.
- A hozzászóláshoz be kell jelentkezni
A 0-ra szükségem van, viszont a többi egyjegyű számok nem kellenek. mivel a lista is kétjegyű.
Vagyis nem jó semmilyen 1, 2, 3, g, 12v, g6
Amire szükség van az: 0, 01, 02 ... 99
- A hozzászóláshoz be kell jelentkezni
Köszönöm szépen a pontosítást.
Ez találatot hoz a 0,0[1-9],és a 10+ feletti számokra. Ha 99 a legnagyobb szám, akkor minimális módosítással finomítható.
- A hozzászóláshoz be kell jelentkezni