usuń poszczególne znaki ze zmiennej za pomocą bash

122

Chcę przeanalizować zmienną (w moim przypadku jest to wersja zestawu deweloperskiego), aby uwolnić ją od kropki ( .). Jeśli version='2.3.3'pożądane wyjście to 233.

Próbowałem jak poniżej, ale wymaga .to zastąpienia inną postacią 2_3_3. Byłoby dobrze, gdyby tr . ''działało.

  1 VERSION='2.3.3' 
  2 echo "2.3.3" | tr . _
prayagupd
źródło
10
Nie, to nie wymaga: echo "2.3.3" | tr -d ..
manatwork,
1
@manatwork Świetnie, to działa. Możesz opublikować jako odpowiedź. Dzięki
prayagupd,
1
Wiele dobrych odpowiedzi. Ale jeśli potrafię odgadnąć cel po raz drugi, ostrzegam o 2.11.3 i 2.1.13 ... ;-) Zastanów się nad dodaniem zer liczbowych.
Rmano,
1
@Rmano Masz na myśli coś takiego VERSION='2.30.3100'? Bez względu na to, co .zostało usunięte, wszystkie odpowiedzi tutaj.
prayagupd
2
@PrayagUpd --- Po prostu miałem na myśli, że jeśli użyjesz liczby po konwersji do porównań (aby powiedzieć, czy „czy ta wersja jest nowsza czy taka sama”), powinieneś zająć się sprawami takimi jak 2.11.3 i 2.1.13 - - wydają się takie same po usunięciu kropek, ale wyraźnie 2.11.3 jest nowszy. Również 2.11.3 jest nowszy niż 2.1.14, ale porównanie 2113 i 2114 doprowadzi do błędnej odpowiedzi. Pamiętam gdzieś błąd z tego powodu ...
Rmano,

Odpowiedzi:

135

Nie ma potrzeby wykonywania programu zewnętrznego. bash„s manipulacji ciąg można go obsługiwać (dostępny również w ksh(skąd pochodzi) i zsh):

$ VERSION='2.3.3'
$ echo "${VERSION//.}"
233

(W instrukcjach dotyczących tych powłok można to znaleźć w sekcji rozszerzania parametrów.)

człowiek w pracy
źródło
19
Dla dalszych szczegółów, składnia powyższej odpowiedzi jest taka ${string//substring/replacement}, w której najwyraźniej brak końcowego ukośnika do przodu i ciągu zastępującego jest interpretowany jako delete . Zobacz tutaj .
sherrellbc
5
man bashJasne , mówi to wyraźnie w sekcji Rozszerzenia parametru powłoki : „ ${parameter/pattern/string}(…) Jeśli łańcuch jest pusty, dopasowania wzorca są usuwane, a /następujący wzorzec może zostać pominięty.”
manatwork
1
Mój problem polegał na tym, że numer wersji pojawił się w ten sposób "1.0.0"i chciałem tylko numer, więc postępuj zgodnie z sugestią @manatwork, że się zmieniłem: "${VERSIONNUM//'"'}"jednak wstawiam nawet, ' ' ponieważ inaczej nie rozpoznałby ""podobnego ciągu do startu.
Alexiscanny,
1
@Alexiscanny, masz na myśli dosłowne "są obecne w wartości? Obawiam się, że liczy się to jako nowe pytanie, ale spróbuj uciec od podwójnego cytatu: "${VERSIONNUM//\"}" pastebin.com/3ECDtkwH
manatwork
1
Wspaniały!! też działa -ash!
Fr0zenFyr
87

W porządku chronologicznym:

tr / sed

echo "$VERSION" | tr -d .
echo "$VERSION" | sed 's/\.//g'

csh / tcsh

echo $VERSION:as/.//

Pociski POSIX:

set -f
IFS=.
set -- $VERSION
IFS=
echo "$*"

ksh / zsh / bash / yash (i busybox ashpo zbudowaniu z ASH_BASH_COMPAT)

echo "${VERSION//.}"

zsh

echo $VERSION:gs/./
Stéphane Chazelas
źródło
1
tr -d usunął nawet pojedynczy znak z zestawu. Dla Ex chcę usunąć DCC_ z „DCC_VersionD”, usuwa DCC i D. Oczekiwany wynik: VersionD. Rzeczywista wydajność: wersja. sed działał jak urok. :) Dzięki za post.
Kayle
20

Oprócz udanych odpowiedzi już istnieje. trZ --deleteopcją można osiągnąć to samo .

echo "2.3.3" | tr --delete .

Co da wynik: 233

daz
źródło
6
na macosie --deleteflaga nie jest rozpoznawana, ale można użyć -dzamiast niej
Anentropic
6

powinieneś spróbować sedzamiast tego

sed 's/\.//g'

fduff
źródło
4
echo "$VERSION" | tr -cd [:digit:]

To zwróci tylko cyfry, bez względu na to, jakie inne znaki są obecne

użytkownik2796674
źródło
4

Perl

$ VERSION='2.3.3'                                     
$ perl -pe 's/\.//g' <<< "$VERSION"           
233

Pyton

$ VERSION='2.3.3'                                     
$ python -c 'import sys;print sys.argv[1].replace(".","")' "$VERSION"
233

Jeśli $VERSIONzawierają tylko cyfry i kropki, możemy zrobić coś jeszcze krótszego:

$ python -c 'print "'$VERSION'".replace(".","")'
233

(uwaga: jest to luka w zabezpieczeniach polegająca na wstrzykiwaniu kodu, chociaż $VERSIONmoże zawierać dowolny znak).

AWK

$ VERSION='2.3.3'
$ awk 'BEGIN{gsub(/\./,"",ARGV[1]);print ARGV[1]}' "$VERSION"
233

Albo to:

$ awk '{gsub(/\./,"")}1' <<< "$VERSION"
233
Sergiy Kolodyazhnyy
źródło