Biorąc pod uwagę nazwę pliku w formularzu someletters_12345_moreleters.ext
, chcę wyodrębnić 5 cyfr i umieścić je w zmiennej.
Aby podkreślić ten punkt, mam nazwę pliku z x liczbą znaków, a następnie pięciocyfrową sekwencję otoczoną pojedynczym podkreśleniem po każdej stronie, a następnie innym zestawem x liczby znaków. Chcę wziąć pięciocyfrowy numer i umieścić go w zmiennej.
Jestem bardzo zainteresowany wieloma różnymi sposobami osiągnięcia tego celu.
abc_12345_def_67890_ghi_def
jest to poprawny wkład. Co chcesz się wydarzyć Załóżmy, że istnieje tylko jedna 5-cyfrowa sekwencja. Nadal maszabc_def_12345_ghi_jkl
lub1234567_12345_1234567
lub12345d_12345_12345e
jako ważny wkład w oparciu o definicję wejścia i większość odpowiedzi poniżej nie zajmie to._
separator, dane wejściowe zawierające ciąg docelowy tylko raz itp.). Odpowiedź najlepiej (najbardziej ogólny i najszybciej) ma po 10 lat, tylko 7 upvotes, podczas gdy inne ograniczone odpowiedzi setki. Sprawia, że tracę wiarę w programistów 😞Odpowiedzi:
Użyj cięcia :
Bardziej ogólny:
źródło
echo
chyba że wiesz na pewno, że zmienne nie mogą zawierać nieregularnych białych znaków lub metaznaków powłoki. Zobacz więcej stackoverflow.com/questions/10067266/…Jeśli x jest stałe, następujące rozwinięcie parametru wykonuje ekstrakcję podłańcucha:
gdzie 12 to przesunięcie (liczone od zera), a 5 to długość
Jeśli podkreślenia wokół cyfr są jedynymi na wejściu, możesz usunąć odpowiednio prefiks i sufiks w dwóch krokach:
Jeśli istnieją inne znaki podkreślenia, jest to prawdopodobnie wykonalne, choć trudniejsze. Jeśli ktoś wie, jak wykonać obie ekspansje w jednym wyrażeniu, też chciałbym wiedzieć.
Oba przedstawione rozwiązania to czysta gra, bez udziału procesu odradzania, a więc bardzo szybko.
źródło
bash: ${${a#*_}%_*}: bad substitution
na moim GNU bash 4.2.45.sh
skrypcie, który prawdopodobnie był kreską. W tym momencie nie mogę już tego uruchomić.:-
„Użyj wartości domyślnych”. Więc${a: -12:5}
daje 5 znaków 12 znaków od końca, a${a: -12:-5}
7 znaków pomiędzy końcem 12 i koniec-5.Ogólne rozwiązanie, w którym liczba może znajdować się w dowolnym miejscu w nazwie pliku, przy użyciu pierwszej z takich sekwencji:
Kolejne rozwiązanie, aby wyodrębnić dokładnie część zmiennej:
Jeśli twoja nazwa pliku ma zawsze format
stuff_digits_...
, możesz użyć awk:Jeszcze jedno rozwiązanie, aby usunąć wszystko oprócz cyfr, użyj
źródło
po prostu spróbuj użyć
cut -c startIndx-stopIndx
źródło
startIndx-$((lastIndx-1))
start=5;stop=9; echo "the rain in spain" | cut -c $start-$(($stop-1))
git log --oneline | head -1 | cut -c 9-(end -1)
line=
git log --oneline | head -1` && echo $ line | cut -c 9 - $ (($ {# line} -1)) `, ale w tym konkretnym przypadku lepiej użyć sed asgit log --oneline | head -1 | sed -e 's/^[a-z0-9]* //g'
W przypadku, gdy ktoś chce bardziej rygorystycznych informacji, możesz je również przeszukać w taki sposób
Wynik:
źródło
${var: -4}
Oto jak bym to zrobił:
Wyjaśnienie:
Specyficzne dla Bash:
[[ ]]
wskazuje wyrażenie warunkowe=~
wskazuje, że warunek jest wyrażeniem regularnym&&
łączy polecenia, jeśli poprzednie polecenie zakończyło się powodzeniemWyrażenia regularne (RE):
_([[:digit:]]{5})_
_
są literałami wyznaczającymi / kotwiczącymi granice dopasowania dla dopasowanego łańcucha()
utwórz grupę przechwytywania[[:digit:]]
to klasa postaci, myślę, że mówi sama za siebie{5}
oznacza dokładnie pięć z poprzedniego znaku, klasy (jak w tym przykładzie) lub grupy musi pasowaćPo angielsku możesz pomyśleć, że zachowuje się tak:
FN
ciąg jest iterowany znak po znaku, dopóki nie zobaczymy,_
w którym momencie grupa przechwytywania jest otwarta i próbujemy dopasować pięć cyfr. Jeśli to dopasowanie zakończy się pomyślnie do tego momentu, grupa przechwytywania zapisuje pięć cyfr, po których następuje przejście. Jeśli następnym znakiem jest an_
, warunek się powiódł, grupa przechwytywania jest dostępna wBASH_REMATCH
iNUM=
można wykonać następną instrukcję. Jeśli którakolwiek część dopasowania nie powiedzie się, zapisane szczegóły są usuwane, a przetwarzanie znak po znaku jest kontynuowane po_
. np. jeśliFN
gdzie_1 _12 _123 _1234 _12345_
, będą cztery fałszywe starty, zanim znajdzie dopasowanie.źródło
cut
). Nie polega również na wykonaniu zewnętrznego polecenia.Dziwię się, że nie pojawiło się to czyste rozwiązanie bash:
Prawdopodobnie chcesz zresetować IFS do wartości, która była wcześniej lub
unset IFS
później!źródło
IFS
IFS=_ read -r _ digs _ <<< "$a"; echo "$digs"
Opierając się na odpowiedzi jora (która nie działa dla mnie):
źródło
cut
prawda.Zgodnie z wymogami
Znalazłem kilka
grep
sposobów, które mogą być przydatne:albo lepiej
A potem ze
-Po
składnią:Lub jeśli chcesz dopasować dokładnie 5 znaków:
Wreszcie, aby zapisać go w zmiennej, wystarczy użyć
var=$(command)
składni.źródło
Invocation as 'egrep' is deprecated; use 'grep -E' instead
. Zredagowałem twoją odpowiedź.Jeśli skupimy się na koncepcji:
„Ciąg (jedna lub kilka) cyfr”
Możemy użyć kilku zewnętrznych narzędzi do wyodrębnienia liczb.
Możemy dość łatwo usunąć wszystkie inne postacie, sed lub tr:
Ale jeśli $ name zawiera kilka serii liczb, powyższe nie powiedzie się:
Jeśli „name = someletters_12345_moreleters_323_end.ext”, to:
Musimy używać regularnych wyrażeń (regex).
Aby wybrać tylko pierwszy przebieg (12345 nie 323) w sed i perl:
Ale równie dobrze moglibyśmy to zrobić bezpośrednio w bash (1) :
To pozwala nam wyodrębnić PIERWSZY ciąg cyfr o dowolnej długości
otoczony dowolnymi innymi tekstami / znakami.
Uwaga :
regex=[^0-9]*([0-9]{5,5}).*$;
dopasuje tylko dokładnie 5-cyfrowy przebieg. :-)(1) : szybciej niż wywołanie zewnętrznego narzędzia dla każdego krótkiego tekstu. Nie szybciej niż całe przetwarzanie w sed lub awk dla dużych plików.
źródło
Bez żadnych podprocesów możesz:
Bardzo mały wariant tego działa również w ksh93.
źródło
Oto rozwiązanie przedrostka-sufiksu (podobne do rozwiązań podanych przez JB i Darrona), które pasuje do pierwszego bloku cyfr i nie zależy od otaczających podkreślników:
źródło
Uwielbiam
sed
zdolność radzenia sobie z grupami wyrażeń regularnych:Nieco bardziej ogólnego rozwiązaniem byłoby nie do przyjęcia, że masz podkreślenia
_
oznakowanie rozpoczęcia swojej sekwencji cyfr, stąd na przykład odciągnięciu wszystkich nie-cyfr dostaniesz przed kolejności:s/[^0-9]\+\([0-9]\+\).*/\1/p
.Więcej informacji na ten temat, na wypadek gdybyś nie był zbyt pewny wyrażeń regularnych:
s
jest dla _s_ubstitute[0-9]+
dopasowuje 1+ cyfry\1
linki do grupy nr 1 wyniku wyrażenia regularnego (grupa 0 to całe dopasowanie, grupa 1 to dopasowanie w nawiasach w tym przypadku)p
Flaga służy do _p_rintingWszystkie sekwencje specjalne
\
są dostępne, abysed
przetwarzanie wyrażeń regularnych działało.źródło
Moja odpowiedź będzie miała większą kontrolę nad tym, co chcesz ze swojego łańcucha. Oto kod, w jaki sposób możesz wyodrębnić
12345
ciągBędzie to bardziej wydajne, jeśli chcesz wyodrębnić coś, co ma dowolne znaki
abc
lub znaki specjalne, takie jak_
lub-
. Na przykład: jeśli Twój ciąg znaków jest taki i chcesz mieć wszystko, co jest posomeletters_
i przed_moreleters.ext
:Za pomocą mojego kodu możesz wspomnieć, czego dokładnie chcesz. Wyjaśnienie:
#*
Usunie poprzedzający ciąg wraz z pasującym kluczem. Klucz, o którym wspominaliśmy_
%
, usunie następujący ciąg, w tym pasujący klucz. Klucz, o którym wspominaliśmy, to „_more *”Zrób kilka eksperymentów sam, a okaże się to interesujące.
źródło
Podany test.txt to plik zawierający „ABCDEFGHIJKLMNOPQRSTUVWXYZ”
źródło
Ok, tutaj jest czysta zamiana parametrów z pustym ciągiem. Zastrzeżenie polega na tym, że zdefiniowałem somethters i moreletters jako tylko postacie. Jeśli są alfanumeryczne, nie zadziała tak jak jest.
źródło
podobny do substr ('abcdefg', 2-1, 3) w php:
źródło
Istnieje również wbudowane polecenie bash „expr”:
źródło
expr
nie jest wbudowany.=~
operatora obsługiwanego przez[[
.Trochę późno, ale właśnie natknąłem się na ten problem i znalazłem:
Użyłem go, aby uzyskać milisekundową rozdzielczość w systemie osadzonym, który nie ma% N dla daty:
źródło
Rozwiązanie bash:
Spowoduje to zablokowanie zmiennej o nazwie
x
. Zmiennax
może być zmieniona na zmienną_
.źródło
Niewygodny koniec, podobny do implementacji JS i Java. Usuń +1, jeśli tego nie chcesz.
Przykład:
Więcej przykładowych połączeń:
Zapraszamy.
źródło