W moim bash
skrypcie mam ciąg i jego prefiks / sufiks. Muszę usunąć prefiks / sufiks z oryginalnego ciągu.
Załóżmy na przykład, że mam następujące wartości:
string="hello-world"
prefix="hell"
suffix="ld"
Jak przejść do następującego wyniku?
result="o-wor"
Odpowiedzi:
źródło
${${string#prefix}%suffix}
ale to nie działa.Za pomocą sed:
W poleceniu sed
^
znak dopasowuje tekst zaczynający się od$prefix
, a znak końcowy$
dopasowuje tekst kończący się na$suffix
.Adrian Frühwirth podaje kilka dobrych uwag w komentarzach poniżej, ale
sed
w tym celu może być bardzo przydatny. Fakt, że treść prefiksu $ i sufiksu $ są interpretowane przez sed, może być albo dobry, albo zły - o ile tylko zwrócisz uwagę, wszystko powinno być w porządku. Piękno polega na tym, że możesz zrobić coś takiego:co może być tym, czego chcesz, i jest zarówno bardziej wymyślne, jak i potężniejsze niż podstawianie zmiennych bash. Jeśli pamiętasz, że z wielką mocą wiąże się wielka odpowiedzialność (jak mówi Spiderman), powinieneś być w porządku.
Szybkie wprowadzenie do sed można znaleźć na stronie stronie http://evc-cit.info/cit052/sed_tutorial.html
Uwaga dotycząca powłoki i użycia ciągów:
W podanym konkretnym przykładzie działałyby również:
... ale tylko dlatego, że:
Zasadniczo dobrą praktyką jest cytowanie ciągu w wierszu poleceń, ponieważ nawet jeśli zawiera spacje, zostanie on przedstawiony poleceniu jako pojedynczy argument. Cytujemy przedrostek $ i sufiks $ z tego samego powodu: każde polecenie edycyjne sed będzie przekazywane jako jeden ciąg. Używamy podwójnych cudzysłowów, ponieważ pozwalają one na zmienną interpolację; gdybyśmy użyli pojedynczych cudzysłowów, komenda sed uzyskałaby dosłowność
$prefix
i na$suffix
pewno nie tego chcieliśmy.Zauważ też, że używam pojedynczych cudzysłowów przy ustawianiu zmiennych
prefix
isuffix
. Z pewnością nie chcemy interpretować niczego w ciągach znaków, dlatego zacytujemy je pojedynczo, aby nie doszło do interpolacji. Ponownie, w tym przykładzie może nie być konieczne, ale bardzo dobrym nawykiem jest wchodzenie w to.źródło
$string
podlega podziałowi słów i dzieleniu. 2)$prefix
i$suffix
może zawierać wyrażenia, któresed
będą interpretować, np. Wyrażenia regularne lub znak używany jako separator, który złamie całe polecenie. 3)sed
Dwukrotne wywołanie nie jest konieczne (możesz-e 's///' -e '///'
zamiast tego), a rurki można również uniknąć. Na przykład, rozważstring='./ *'
i / lubprefix='./'
zobacz, jak okropnie pęka z powodu1)
i2)
./
, więc użyłemsed "s#^$prefix##
zamiast tego. (Kruchość: nazwy plików nie mogą zawierać#
. Ponieważ kontroluję pliki, jesteśmy bezpieczni.)#
jako separatora sed oznacza, że nie możesz obsługiwać plików zawierających ten znak.Czy znasz długość swojego przedrostka i przyrostka? W Twoim przypadku:
Lub bardziej ogólnie:
Ale rozwiązanie Adriana Frühwirtha jest świetne ! Nie wiedziałem o tym!
źródło
Używam grep do usuwania prefiksów ze ścieżek (które nie są dobrze obsługiwane
sed
):\K
usuwa z meczu wszystkie postacie przed nim.źródło
grep -P
jest niestandardowym rozszerzeniem. Więcej mocy, jeśli jest obsługiwana na twojej platformie, ale jest to wątpliwa rada, jeśli twój kod musi być w miarę przenośny.grep
. Wcześniejsze wersje faktycznie miały-P
opcję z BSD,grep
ale ją usunęły.Uwagi:
Prefiks # $: dodanie # gwarantuje, że podciąg „hell” zostanie usunięty tylko wtedy, gdy zostanie znaleziony na początku. Sufiks% $: dodanie% gwarantuje, że podciąg „ld” zostanie usunięty tylko, jeśli zostanie znaleziony na końcu.
Bez nich podciągi „hell” i „ld” zostaną usunięte wszędzie, nawet w środku.
źródło
/
zaraz po ciągu, po co to jest?Korzystanie z
=~
operatora :źródło
Małe i uniwersalne rozwiązanie:
źródło
expr
. Było to swego rodzaju wygodne narzędzie do zlewów kuchennych w czasach oryginalnej skorupy Bourne'a, ale jest już dawno minione.Za pomocą @Adrian Frühwirth odpowiedź:
użyj tego w ten sposób
źródło
Korzystam z grup przechwytywania w wyrażeniach regularnych:
((?:(?!(${suffix})).)*)
upewnia się, że zawartość${suffix}
zostanie wykluczona z grupy przechwytywania. Na przykład jest to ciąg równoważny z[^A-Z]*
. W przeciwnym razie otrzymasz:źródło