Я хотел бы удалить последний символ строки, я попробовал этот маленький скрипт:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
но он печатает "lkj", что я делаю не так?
Я хотел бы удалить последний символ строки, я попробовал этот маленький скрипт:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
но он печатает "lkj", что я делаю не так?
Ответы:
В оболочке POSIX синтаксис ${t:-2}
означает что-то другое - он расширяется до значения t
if t
, установленного и отличного от NULL, а в противном случае до значения 2
. Чтобы обрезать один символ с помощью раскрытия параметров, вы, вероятно, захотите следующий синтаксис:${t%?}
Обратите внимание , что в ksh93
, bash
или zsh
, ${t:(-2)}
или ${t: -2}
(обратите внимание на пробел) являются законными как расширение подстроки , но, вероятно , не то , что вы хотите, так как они возвращают подстроки , начиная с позицией 2 символа в с конца (т.е. удаляет первый символ i
из строка ijk
).
См. Раздел «Расширение параметров оболочки» Справочного руководства Bash для получения дополнительной информации:
${parameter%word}
удаляет сопоставление с самым коротким суффиксным шаблоном word
- см. раздел «Расширение параметров»man bash
С bash
4.2 и выше, вы можете сделать:
${var::-1}
Пример:
$ a=123
$ echo "${a::-1}"
12
Обратите внимание, что для более старых версий bash
(например, bash 3.2.5
в OS X) вы должны оставлять пробелы между двоеточиями и после них:
${var: : -1}
bash
версии 4.2-alpha и выше, слишком плохая версия, к которой у меня есть доступ, более ранняя. : - /
${var:offset:lenght}
была добавлена только в bash 4.2
. Может быть, OSX добавить свой собственный патч для bash
.
для удаления последних n
символов из строки, которая не использует sed
ИЛИ awk
:
> echo lkj | rev | cut -c (n+1)- | rev
так, например, вы можете удалить последний символ, one character
используя это:
> echo lkj | rev | cut -c 2- | rev
> lk
с rev
manpage:
ОПИСАНИЕ
Утилита rev копирует указанные файлы в стандартный вывод, меняя порядок символов в каждой строке. Если файлы не указаны, читается стандартный ввод.
ОБНОВИТЬ:
если вы не знаете длину строки, попробуйте:
$ x="lkj"
$ echo "${x%?}"
lk
С помощью sed это должно быть так же быстро, как
sed 's/.$//'
Ваше единственное эхо тогда echo ljk | sed 's/.$//'
.
Используя это, строка из 1 строки может быть любого размера.
Несколько вариантов в зависимости от оболочки:
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 *?
Обратите внимание, что хотя все должны удалять последний символ , вы обнаружите, что некоторые реализации (те, которые не поддерживают многобайтовые символы) вместо этого отбрасывают последний байт (так что, вероятно, испортил бы последний символ, если он был многобайтовым). ).
Предполагается, что expr
вариант $t
не заканчивается более чем одним символом новой строки. Он также вернет ненулевой статус выхода, если полученная строка окажется 0
( 000
или даже -0
с некоторыми реализациями). Это также может дать неожиданные результаты, если строка содержит недопустимые символы.
t=${t%?}
это не Bourne, но вы вряд ли встретите Bourne shell в наши дни. ${t%?}
работает во всех других, хотя.
fish
идет работа 2.3.0, которая представила string
встроенную версию, не была выпущена во время Q & A. В версии, на которой я ее тестирую, вам нужны string replace -r '(?s).\z' '' -- $t
(и я ожидаю, что они захотят это изменить, они должны изменить флаги, которые они передают в PCRE) или более замысловатые. Это также плохо работает с символами новой строки, и я знаю, что они планируют изменить это также.
Самый портативный и самый короткий ответ почти наверняка:
${t%?}
Это работает в bash, sh, ash, dash, busybox / ash, zsh, ksh и т. Д.
Он работает с использованием расширения параметров старой школы. В частности, %
указывается, чтобы удалить наименьший соответствующий суффикс соответствия параметра, t
который соответствует шаблону глобуса ?
(т. Е. Любому символу).
См. «Удалить самый маленький шаблон суффикса» здесь для более подробного объяснения и дополнительной информации. Также см. Документы для вашей оболочки (например:) в man bash
разделе «Расширение параметров».
В качестве примечания: если вы хотите вместо этого удалить первый символ, вы должны использовать ${t#?}
, так как #
совпадения начинаются с начала строки (префикс), а не с конца (суффикс).
Также стоит отметить, что как %
и , так и #
иметь %%
и ##
версии, которые соответствуют самой длинной версии данного шаблона, а не самой короткой. Оба ${t%%?}
и ${t##?}
будут делать то же самое, что и их единственный оператор в этом случае (так что не добавляйте лишний лишний символ). Это потому, что данный ?
шаблон соответствует только одному символу. Смешайте *
с некоторыми не подстановочными знаками, и все становится более интересным с %%
и ##
.
Понимание расширений параметров или, по крайней мере, знание об их существовании и умение их искать, невероятно полезно для написания и расшифровки сценариев оболочки многих разновидностей. Расширения параметров часто выглядят как тайная оболочка вуду для многих людей, потому что ... ну ... они являются тайной оболочкой вуду (хотя довольно хорошо документированы, если вы знаете, что нужно искать "расширение параметров"). Определенно хорошо иметь в поясе инструментов, когда вы застряли в оболочке.
Вы также можете использовать, head
чтобы распечатать все, кроме последнего символа.
$ s='i am a string'
$ news=$(echo -n $s | head -c -1)
$ echo $news
i am a strin
Но, к сожалению, некоторые версии head
не включают ведущий -
вариант. Это тот случай, head
который идет с OS X.
Просто для завершения некоторых возможных применений чистого 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/%\ /}'"
Первый синтаксис берет подстроку из строки, синтаксис
Для второго, обратите внимание на знак, который означает «с конца строки», а синтаксис
${STRING:OFFSET:LENGTH}
%
${STRING/PATTERN/SUBSTITUTION}
И вот две более короткие формы вышеупомянутого
echo "Removed trailing whitespace: '${STR::-1}'"
echo "Removed trailing whitespace: '${STR%\ }'"
Здесь снова обратите внимание на %
знак, означающий «Удалить (т. Е. Заменить на») самый короткий совпавший шаблон (здесь представленный пробелом «\» от конца ПАРАМЕТРА - здесь с именем STR