Po pierwsze, powinieneś wyraźnie powiedzieć, czego chcesz. Jeśli wiesz, że ciąg się kończy .rtfi chcesz usunąć .rtf, możesz użyć var2=${var%.rtf}. Jeśli nie wiesz, co to jest przyrostek, ale chcesz usunąć wszystko, zaczynając od ostatniego ., możesz użyć var2=${var%.*}. Jeśli chcesz zachować wszystko na pierwszym miejscu ., możesz użyć var2=${var%%.*}. Te dwie ostatnie opcje mają ten sam wynik, jeśli jest tylko jeden okres, ale jeśli może być więcej niż jeden, powinieneś zdecydować, który chcesz.
Jeśli naprawdę chcesz zawsze usuwać dokładną liczbę znaków, oto kilka opcji.
Podałeś konkretnie bash, więc zaczniemy od wbudowanych bash. Najdłużej działała ta sama składnia usuwania sufiksów, której użyłem powyżej: aby usunąć cztery znaki, użyj var2=${var%????}. Musisz usunąć jeden znak zapytania na znak, więc staje się nieporęczny w przypadku większych długości podciągu.
Nieco nowszy jest podciąg ekstrakcji: var2=${var::${#var}-4}. Tutaj możesz wstawić dowolną liczbę zamiast, 4aby usunąć inną liczbę znaków. (Symbol ${#var}zastępowany jest długością łańcucha, więc w rzeczywistości prosi o zachowanie pierwszych (długości - 4) znaków).
Nowsze wersje bash (szczególnie 4+, co oznacza, że ta dostarczana z MacOS nie będzie działać) pozwalają to uprościć var2=${var::-4}.
Jeśli tak naprawdę nie używasz bash, ale jakiejś innej powłoki typu POSIX, usuwanie sufiksu będzie nadal działać, nawet w zwykłym starym myślniku (gdzie żadna reszta nie będzie). W zsh, że wszystkie prace, ale trzeba umieścić 0między dwukropkiem: var2=${var:0:-4}itd. W ksh, potrzebny jest 0, a także mieć możliwość korzystania z wyraźnej długości 4 wyrażenie: var2=${var:0:${#var}-4}.
Możesz oczywiście użyć zastępowania poleceń, aby to zrobić za pomocą programu narzędziowego; jest wiele, które będą działać, ale coś takiego var2=$(cut -c -4 <<<"$var")jest prawdopodobnie najkrótszą opcją.
Odpowiedź w czystej powłoce i będzie działać w BASH 3.x, który można znaleźć w wielu systemach, które odmówiły wdrożenia BASH 4.x z powodu problemów licencyjnych.
David W.
1
Jest to fajne, ponieważ jest odporne na krótsze łańcuchy; warianty przesunięcia indeksu zawodzą.
Raphael
działa w bash 3.2.25 - najlepsza możliwa odpowiedź - tylko to, czego szukałem
capser
Doskonała odpowiedź. Co powiesz na usunięcie z przodu sznurka?
user2023370 24.0119
3
@ user2023370 Zapoznanie się z dokumentacją powinno ujawnić, że istnieje odpowiednie zastąpienie parametru ${var#????}.
tripleee
48
Dla mnie zadziałało:
echo "hello world"| rev | cut -c5-| rev
# hello w
Ale użyłem go do przycięcia linii w pliku, dlatego wygląda to niezręcznie. Rzeczywistym zastosowaniem było:
cat somefile | rev | cut -c5-| rev
cutprowadzi cię tylko do przycinania z pewnej pozycji początkowej, co jest złe, jeśli potrzebujesz rzędów o zmiennej długości. To rozwiązanie odwraca ( rev) ciąg znaków i teraz odnosimy się do jego końcowej pozycji, a następnie używa, cutjak wspomniano, i odwraca (ponownie rev) do pierwotnej kolejności.
To nie jest poprawne i nie jest odpowiedzią na to, o co się pyta. revodwraca wiersze, a nie ciągi znaków. echo $SOME_VAR | rev | ...prawdopodobnie nie zachowa się tak, jak można by się spodziewać.
Odpowiedzi:
Po pierwsze, powinieneś wyraźnie powiedzieć, czego chcesz. Jeśli wiesz, że ciąg się kończy
.rtf
i chcesz usunąć.rtf
, możesz użyćvar2=${var%.rtf}
. Jeśli nie wiesz, co to jest przyrostek, ale chcesz usunąć wszystko, zaczynając od ostatniego.
, możesz użyćvar2=${var%.*}
. Jeśli chcesz zachować wszystko na pierwszym miejscu.
, możesz użyćvar2=${var%%.*}
. Te dwie ostatnie opcje mają ten sam wynik, jeśli jest tylko jeden okres, ale jeśli może być więcej niż jeden, powinieneś zdecydować, który chcesz.Jeśli naprawdę chcesz zawsze usuwać dokładną liczbę znaków, oto kilka opcji.
Podałeś konkretnie bash, więc zaczniemy od wbudowanych bash. Najdłużej działała ta sama składnia usuwania sufiksów, której użyłem powyżej: aby usunąć cztery znaki, użyj
var2=${var%????}
. Musisz usunąć jeden znak zapytania na znak, więc staje się nieporęczny w przypadku większych długości podciągu.Nieco nowszy jest podciąg ekstrakcji:
var2=${var::${#var}-4}
. Tutaj możesz wstawić dowolną liczbę zamiast,4
aby usunąć inną liczbę znaków. (Symbol${#var}
zastępowany jest długością łańcucha, więc w rzeczywistości prosi o zachowanie pierwszych (długości - 4) znaków).Nowsze wersje bash (szczególnie 4+, co oznacza, że ta dostarczana z MacOS nie będzie działać) pozwalają to uprościć
var2=${var::-4}
.Jeśli tak naprawdę nie używasz bash, ale jakiejś innej powłoki typu POSIX, usuwanie sufiksu będzie nadal działać, nawet w zwykłym starym myślniku (gdzie żadna reszta nie będzie). W zsh, że wszystkie prace, ale trzeba umieścić
0
między dwukropkiem:var2=${var:0:-4}
itd. W ksh, potrzebny jest 0, a także mieć możliwość korzystania z wyraźnej długości 4 wyrażenie:var2=${var:0:${#var}-4}
.Możesz oczywiście użyć zastępowania poleceń, aby to zrobić za pomocą programu narzędziowego; jest wiele, które będą działać, ale coś takiego
var2=$(cut -c -4 <<<"$var")
jest prawdopodobnie najkrótszą opcją.źródło
Możesz to zrobić w następujący sposób:
źródło
bash
4+, ale we wcześniejszej wersji możesz użyć nieco dłuższego${v::${#v}-4}
.${v::-4}
wykrzykiwa „zsh: oczekiwany nawias zamykający”. Ale poniższa odpowiedź @fredtantini${v:0:-4}
działa dobrze.Aby usunąć cztery znaki z końca ciągu, użyj
${var%????}
.Aby usunąć wszystko po ostatnim
.
użyciu${var%.*}
.źródło
${var#????}
.Dla mnie zadziałało:
Ale użyłem go do przycięcia linii w pliku, dlatego wygląda to niezręcznie. Rzeczywistym zastosowaniem było:
cut
prowadzi cię tylko do przycinania z pewnej pozycji początkowej, co jest złe, jeśli potrzebujesz rzędów o zmiennej długości. To rozwiązanie odwraca (rev
) ciąg znaków i teraz odnosimy się do jego końcowej pozycji, a następnie używa,cut
jak wspomniano, i odwraca (ponownierev
) do pierwotnej kolejności.źródło
rev
odwraca wiersze, a nie ciągi znaków.echo $SOME_VAR | rev | ...
prawdopodobnie nie zachowa się tak, jak można by się spodziewać.Korzystanie ze zmiennego rozszerzenia / zamiany podciągów :
Możesz więc zrobić:
Alternatywnie,
Jeśli masz zawsze te same 4 litery
Jeśli zawsze kończy się na
.xyz
:Możesz także użyć długości ciągu:
lub po prostu
echo ${var::-4}
źródło
len=${#var}; echo ${var::len-4}
można skrócić doecho ${var:0:-4}
:-) EDYCJA: lub jak zauważył @iyonizer, po prostuecho ${var::-4}
...Możesz użyć sed,
Przykład:
źródło
var2
?Wypróbowałem następujące i zadziałało to dla mnie:
Wynik:
hel
źródło
Mam nadzieję, że poniższy przykład pomoże,
echo ${name:0:$((${#name}-10))}
->${name:start:len}
start
jest punktem początkowym łańcuchalen
to długość ciągu, który należy usunąć.Przykład:
Wynik:
Uwaga: Bash 4.2 dodał obsługę ujemnego podłańcucha
źródło
To działało dla mnie, obliczając rozmiar łańcucha.
Łatwo jest powtórzyć wartość, którą chcesz zwrócić, a następnie zapisać ją jak poniżej
źródło
W takim przypadku możesz użyć basename przy założeniu, że masz taki sam przyrostek na plikach, które chcesz usunąć.
Przykład:
Jeśli nie znasz przyrostka i chcesz usunąć wszystko po ostatniej kropce włącznie:
% oznacza chop,. to, co siekasz, * to symbol wieloznaczny
źródło