Chciałbym usunąć ostatni znak ciągu, wypróbowałem ten mały skrypt:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
ale wypisuje „lkj”, co robię źle?
shell-script
string
użytkownik3581976
źródło
źródło
${parameter%word}
usuwa najkrótsze dopasowanie wzorca sufiksuword
- patrz sekcja Rozbudowa parametruman bash
W wersji
bash
4.2 i nowszej możesz:Przykład:
Zauważ, że w przypadku starszych
bash
(na przykładbash 3.2.5
w systemie OS X) należy pozostawić spacje między dwukropkami i po nich:źródło
bash
wersji 4.2-alfa i wyższej, szkoda, że wersja, do której mam dostęp, jest wcześniejsza. : - /${var:offset:lenght}
została dodana tylko wbash 4.2
. Może OSX doda własną łatkębash
.do usuwania ostatnich
n
znaków z linii, która nie używased
ORawk
:więc na przykład możesz usunąć ostatni znak,
one character
używając tego:ze
rev
strony man:AKTUALIZACJA:
jeśli nie znasz długości łańcucha, spróbuj:
źródło
Używanie sed powinno być tak szybkie jak
Twoje pojedyncze echo jest wtedy
echo ljk | sed 's/.$//'
.Korzystając z tego, łańcuch 1-liniowy może mieć dowolny rozmiar.
źródło
Kilka opcji w zależności od powłoki:
t=${t%?}
t=`expr " $t" : ' \(.*\).'`
t=${t[1,-2]}
t=${t:0:-1}
t=${t:0:${#t}-1}
t=${t/%?}
t=${t/~(E).$/}
@ {t=$1} ~~ $t *?
Zauważ, że chociaż wszystkie powinny usuwać ostatni znak , niektóre implementacje (te, które nie obsługują znaków wielobajtowych) usuwają zamiast tego ostatni bajt (więc prawdopodobnie uszkodziłby ostatni znak, jeśli byłby wielobajtowy ).
expr
Wariant zakłada$t
nie kończy się w więcej niż jeden znak nowej linii. Zwróci również niezerowy status wyjścia, jeśli powstały ciąg będzie0
(000
lub nawet-0
z niektórymi implementacjami). Może również dawać nieoczekiwane wyniki, jeśli ciąg znaków zawiera nieprawidłowe znaki.źródło
t=${t%?}
to nie Bourne, ale w dzisiejszych czasach raczej nie spotkasz powłoki Bourne'a.${t%?}
działa jednak we wszystkich pozostałych.fish
jest w toku. 2.3.0, która wprowadziłastring
wbudowaną wersję, nie została wydana w czasie pytań i odpowiedzi. W wersji, na której testuję, potrzebujeszstring replace -r '(?s).\z' '' -- $t
(i spodziewałbym się, że chcieliby to zmienić, powinni zmienić flagi, które przekazują do PCRE) lub bardziej skomplikowane. Słabo radzi sobie również z postaciami nowej linii i wiem, że planują to również zmienić.Najbardziej przenośna i najkrótsza odpowiedź to prawie na pewno:
${t%?}
Działa to w bash, sh, ash, dash, busybox / ash, zsh, ksh itp.
Działa przy użyciu old-schoolowego rozszerzenia parametrów powłoki. W szczególności
%
określa, aby usunąć najmniejszy zgodny sufiks parametru,t
który pasuje do wzorca globalnego?
(tj. Dowolny znak).Zobacz „Usuń najmniejszy wzór sufiksu” tutaj, aby uzyskać (znacznie) bardziej szczegółowe wyjaśnienie i dodatkowe tło. Zobacz także dokumentację swojej powłoki (np .
man bash
:) w „rozszerzaniu parametrów”.Na marginesie, jeśli zamiast tego chcesz usunąć pierwszy znak, użyj go
${t#?}
, ponieważ#
dopasowania z przodu łańcucha (przedrostek) zamiast z tyłu (przyrostek).Warto również zauważyć, że zarówno
%
i#
mają%%
i##
wersje, które pasują do najdłuższej wersji danego wzorca zamiast najkrótszej. Oba${t%%?}
i${t##?}
w tym przypadku zrobiłyby to samo, co ich pojedynczy operator (więc nie dodawaj niepotrzebnego dodatkowego znaku). Jest tak, ponieważ podany?
wzorzec pasuje tylko do jednego znaku. Wymieszaj*
z kilkoma symbolami wieloznacznymi i rzeczy stają się bardziej interesujące z%%
i##
.Zrozumienie rozszerzeń parametrów, a przynajmniej wiedza o ich istnieniu i umiejętność ich wyszukiwania, jest niezwykle przydatna do pisania i deszyfrowania skryptów powłoki wielu smaków. Rozszerzenia parametrów często wyglądają jak tajemne voodoo dla wielu ludzi, ponieważ ... no cóż ... są tajemnymi voodoo shellami (chociaż całkiem dobrze udokumentowane, jeśli wiesz, jak szukać „rozszerzenia parametrów”). Zdecydowanie dobrze jest mieć pasek narzędzi, gdy utkniesz w skorupie.
źródło
Otrzymasz podciąg od 0 do długości łańcucha -1. Zauważ jednak, że to odejmowanie jest specyficzne dla bash i nie będzie działać na innych powłokach.
Na przykład
dash
nie jest w stanie nawet parsowaćNa przykład w systemie Ubuntu
/bin/sh
jestdash
źródło
Możesz także użyć
head
do wydrukowania wszystkich znaków oprócz ostatniego.Ale niestety niektóre wersje
head
nie zawierają wiodącej-
opcji. Tak jest w przypadkuhead
systemu OS X.źródło
Łatwo jest to zrobić, używając wyrażenia regularnego:
źródło
Niektóre udoskonalenia. Aby usunąć więcej niż jeden znak, możesz dodać wiele znaków zapytania. Na przykład, aby usunąć dwa ostatnie znaki ze zmiennej:
$SRC_IP_MSG
możesz użyć:źródło
Aby ukończyć niektóre możliwe zastosowania czystej bash:
Pierwsza składnia pobiera podciąg z ciągu, składnia to Dla drugiego zauważ znak, który oznacza „z końca linii”, a składnia to
${STRING:OFFSET:LENGTH}
%
${STRING/PATTERN/SUBSTITUTION}
A oto dwie krótsze formy wyżej wymienionych
Tutaj zauważ ponownie
%
znak oznaczający „Usuń (to znaczy zamień na”) najkrótszy dopasowany wzór (tutaj reprezentowany przez spację „\” z końca PARAMETRU - tutaj o nazwie STRźródło
Jak możemy również użyć php w wierszu poleceń lub skryptów powłoki. Czasami jest przydatny do parsowania chirurgicznego.
Z lamówką:
źródło
W ksh:
źródło