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?
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?
Odpowiedzi:
W powłoce POSIX składnia ${t:-2}oznacza coś innego - rozwija się do wartości tif tjest ustawiona i różna od null, a w przeciwnym razie do wartości 2. Aby przyciąć pojedynczy znak poprzez rozwinięcie parametru, prawdopodobnie potrzebna jest składnia${t%?}
Zauważ, że w ksh93, bashalbo zsh, ${t:(-2)}albo ${t: -2}(uwaga przestrzeni) są prawną jako ekspansji podciągu ale prawdopodobnie nie są, co chcesz, ponieważ zwracają podciąg rozpoczynający się w położeniu 2 znaki od końca (czyli usuwa pierwszy znak iz następujących ciąg ijk).
Aby uzyskać więcej informacji, zobacz sekcję Rozszerzanie parametrów powłoki podręcznika Bash Reference:
${parameter%word}usuwa najkrótsze dopasowanie wzorca sufiksu word- patrz sekcja Rozbudowa parametruman bash
W wersji bash4.2 i nowszej możesz:
${var::-1}
Przykład:
$ a=123
$ echo "${a::-1}"
12
Zauważ, że w przypadku starszych bash(na przykład bash 3.2.5w systemie OS X) należy pozostawić spacje między dwukropkami i po nich:
${var: : -1}
bashwersji 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 w bash 4.2. Może OSX doda własną łatkę bash.
do usuwania ostatnich nznaków z linii, która nie używa sedOR awk:
> echo lkj | rev | cut -c (n+1)- | rev
więc na przykład możesz usunąć ostatni znak, one characterużywając tego:
> echo lkj | rev | cut -c 2- | rev
> lk
ze revstrony man:
OPIS
Narzędzie rev kopiuje określone pliki na standardowe wyjście, odwracając kolejność znaków w każdym wierszu. Jeśli nie określono żadnych plików, standardowe wejście jest odczytywane.
AKTUALIZACJA:
jeśli nie znasz długości łańcucha, spróbuj:
$ x="lkj"
$ echo "${x%?}"
lk
Używanie sed powinno być tak szybkie jak
sed 's/.$//'
Twoje pojedyncze echo jest wtedy echo ljk | sed 's/.$//'.
Korzystając z tego, łańcuch 1-liniowy może mieć dowolny rozmiar.
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 ).
exprWariant zakłada $tnie 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ędzie 0( 000lub nawet -0z niektórymi implementacjami). Może również dawać nieoczekiwane wyniki, jeśli ciąg znaków zawiera nieprawidłowe znaki.
t=${t%?}to nie Bourne, ale w dzisiejszych czasach raczej nie spotkasz powłoki Bourne'a. ${t%?}działa jednak we wszystkich pozostałych.
fishjest w toku. 2.3.0, która wprowadziła stringwbudowaną wersję, nie została wydana w czasie pytań i odpowiedzi. W wersji, na której testuję, potrzebujesz string 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, tktó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.
t=lkj
echo ${t:0:${#t}-1}
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 dashnie jest w stanie nawet parsować
echo ${t:0:$(expr ${#t} - 1)}
Na przykład w systemie Ubuntu /bin/shjestdash
Możesz także użyć headdo wydrukowania wszystkich znaków oprócz ostatniego.
$ s='i am a string'
$ news=$(echo -n $s | head -c -1)
$ echo $news
i am a strin
Ale niestety niektóre wersje headnie zawierają wiodącej -opcji. Tak jest w przypadku headsystemu OS X.
Aby ukończyć niektóre możliwe zastosowania czystej bash:
#!/bin/bash
# Testing substring removal
STR="Exemple string with trailing whitespace "
echo "'$STR'"
echo "Removed trailing whitespace: '${STR:0:${#STR}-1}'"
echo "Removed trailing whitespace: '${STR/%\ /}'"
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
echo "Removed trailing whitespace: '${STR::-1}'"
echo "Removed trailing whitespace: '${STR%\ }'"
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