Я хотів би видалити останній символ рядка, я спробував цей маленький сценарій:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
але він друкує "lkj", що я роблю неправильно?
Я хотів би видалити останній символ рядка, я спробував цей маленький сценарій:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
але він друкує "lkj", що я роблю неправильно?
Відповіді:
У оболонці POSIX синтаксис ${t:-2}означає щось інше - він розширюється до значення, tякщо tвстановлено і ненулеве значення, інакше до значення 2. Щоб обрізати один символ за допомогою розширення параметра, потрібен синтаксис, який, мабуть, є${t%?}
Зверніть увагу , що в ksh93, bashабо zsh, ${t:(-2)}або ${t: -2}(зверніть увагу на пробіл) є законними як розширення підрядка , але, ймовірно , не те , що ви хочете, так як вони повертають підрядка , починаючи з позицією 2 символи в с кінця (тобто видаляє перший символ iз рядок ijk).
Докладнішу інформацію див. У розділі Розширення параметрів оболонки в Довідковому посібнику Bash:
${parameter%word}видаляє найкоротший суфічний узор word- див. розділ Розширення параметрівman bash
З bash4.2 і вище, ви можете:
${var::-1}
Приклад:
$ a=123
$ echo "${a::-1}"
12
Зауважте, що для старих bash(наприклад, bash 3.2.5для ОС X) слід залишати пробіли між колонами та після них:
${var: : -1}
bashверсії 4.2-альфа і вище, занадто погана версія, до якої я маю доступ. : - /
${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
з revmanpage:
ОПИС
Утиліта 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. ${t%?}Хоча працює у всіх інших.
fishце незавершена робота. 2.3.0, який представив stringвбудований, не був випущений під час Q&A. З версією, на якій я її тестую, вам знадобиться string replace -r '(?s).\z' '' -- $t(і я б очікував, що вони захочуть це змінити, вони повинні змінити прапори, які вони передають PCRE) або більш перекручені. Він також погано має справу з символами нового рядка, і я знаю, що вони також планують змінити це.
Найбільш портативна і найкоротша відповідь майже напевно:
${t%?}
Це працює в bash, sh, ash, dash, busybox / ash, zsh, ksh тощо.
Він працює за допомогою розширення параметрів оболонки Old-School. Зокрема, %вказує на видалення найменшого суфікса параметра, 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що поставляється з ОС X.
Це досить просто зробити, використовуючи регулярний вираз:
n=2
echo "lkj" | sed "s/\(.*\).\{$n\}/\1/"
Просто для завершення деяких можливих застосувань чистого башу:
#!/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