2013-05-29 14 views
6

Mam zestaw poprawnych znaków [0-9a-z_] i zmienną, której przypisano jeden z tych znaków. Co chcę zrobić, to móc zwiększyć tę zmienną do następnej w zestawie.bash - zmienne przyrostowe zawierające litery

Jeśli zajdzie taka potrzeba, zajmuję się "specjalnymi" przypadkami, w których liczba ta zwiększyłaby się z "9" do "a" i "z" do "_", ale nie wiem, jak zwiększać liczbę liter.

#!/bin/bash 
y=b 
echo $y # this shows 'b' 
y=$((y+1)) 
echo $y # this shows '1', but I want it to be 'c' 
+0

szukasz to? http://stackoverflow.com/a/13128083/297323 –

Odpowiedz

6
y=b 
echo "$y" # this shows 'b' 
y=$(echo "$y" | tr "0-9a-z" "1-9a-z_") 
echo "$y" # this shows 'c' 

Zauważ, że to nie dotyczy przypadku, w którym $ y = "_" (nie wiesz, czego chcesz, a tak czy inaczej prawdopodobnie będzie wymagać oddzielnej obsługi), a jeśli $ y ma więcej niż jeden znak, to "przyrost" wszystkich z nich (np "10" -> "21", "09g" -> "1ah" itd.).

+0

Tego właśnie szukałem. Potrafię sobie radzić w specjalnych przypadkach, w których $ y ma więcej niż jeden znak lub gdy jest równy "_". Jest to o wiele ładniejsze rozwiązanie niż ta brzydka tablica, której używałem. Dzięki! –

+0

'y = b; y = $ (tr "0-9a0-z" "1-9a-z_" <<< $ y); echo $ y; ' – dylnmc

3

Może to być rozwiązanie:

a=({0..9} {a..z} _) 
echo ${a[*]} 
yc=11 
echo ${a[yc]} 
((++yc)) 
echo ${a[yc]} 
echo ${a[++yc]} 

#Alternative 
declare -A h 
# Fill the has point to the next character 
for((i=0;((i+1))<${#a[*]};++i)) { h[${a[i]}]=${a[i+1]};} 
y=b 
echo $y, ${h[$y]} 

wyjściowa:

0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z _ 
b 
c 
d 
b, c 
+1

To działa, a właściwie jest bardzo zbliżone do tego, co sam zbudowałem, ale nie jest to najbardziej eleganckie rozwiązanie. Musi być lepszy sposób ... –

+0

W rzeczywistości używa się dokładnie tego samego w idei, co zaakceptowałeś, ale to zużywa mniej zasobów. Przynajmniej dwa widelce mniej i brak exec do innych programów zewnętrznych. – TrueY

1

Możesz zacząć od tego:

echo 0x$(($(printf "%x" "'b'") + 1)) | xxd -r 
-1

Napisałem to dla projektu, używa ono chr and ord fucntions (także tu gdzieś znalezionego) i trochę czystego basha (tylko zewnętrzne wywoływane w funkcji to tr), jeśli robisz więcej niż 100 znaków, użyłbym coś innego, ale dla krótkich łańcuchów w moim testowaniu jego faktycznie nieco szybciej niż pyton. Również ten skrypt zmniejsza liczbę znaków wejściowych, trzeba będzie go zmienić na wielkie litery. po umieszczeniu tych funkcji w skrypcie (lub wyciąć i wkleić do muszli) można po prostu zrobić

inc_string abz9z9

i wrócić.

aca0a0

chr() { 
    [ "$1" -lt 256 ] || return 1 
    printf "\\$(printf '%03o' "$1")" 
} 

ord() { 
    LC_CTYPE=C printf '%d' "'$1" 
} 

inc_string() 
{ 
string="$1"; 
lcstring=$(echo $string | tr '[:upper:]' '[:lower:]'); 


for ((position=$((${#lcstring}-1));position>=0;position--));do 

    if [ "${lcstring:position:1}" = 'z' ]; then 
    if [ "$position" -eq "$((${#lcstring}-1))" ]; then 
     newstring="${lcstring:0:$(($position))}a"; 
     lcstring="$newstring"; 
    elif [ "$position" -eq "0" ]; then 
     newstring="a${lcstring:$((position+1))}"; 
     echo $newstring; 
     break; 
    else 
     newstring="${lcstring:0:$(($position))}a${lcstring:$((position+1))}"; 
     lcstring="$newstring"; 
    fi 
    elif [ "${lcstring:position:1}" = '9' ]; then 
    if [ "$position" -eq "$((${#lcstring}-1))" ]; then 
     newstring="${lcstring:0:$(($position))}0"; 
     lcstring="$newstring"; 
    elif [ "$position" -eq "0" ]; then 
     newstring="0${lcstring:$((position+1))}"; 
     echo $newstring; 
     break; 
    else 
     newstring="${lcstring:0:$(($position))}0${lcstring:$((position+1))}"; 
     lcstring="$newstring"; 
    fi 
    else 
    if [ "$position" -eq "$((${#lcstring}-1))" ]; then 
     newstring="${lcstring:0:$(($position))}$(chr $(($(ord ${lcstring:position})+1)))"; 
     echo $newstring; 
     break; 
    elif [ "$position" -eq "0" ]; then 
     newstring="$(chr $(($(ord ${lcstring:position})+1)))${lcstring:$((position+1))}"; 
     echo $newstring; 
     break; 
    else 
     newstring="${lcstring:0:$(($position))}$(chr $(($(ord ${lcstring:position})+1)))${lcstring:$(($position+1))}"; 
     echo $newstring; 
     break;    
    fi 
    fi 
done 

} 
Powiązane problemy