У меня есть строки в форме wva/sia/e1
, bct/e2
, sv/de/e11
. Это всегда <Part1>/e<NUM>
или <Part1>/<Part2>/e<NUM>
. То, что я хочу, должно укоротить строки путем хранения первых букв частей и отказа от наклонных черт и e:
wva/sia/e1 > ws1
bct/e2 > b2
sv/de/e11 > sd11
Как я могу сделать ту внутреннюю часть sh сценарий?
Править: Строка представляет имя задания:
[...]
job_name=$1 # e.g. 'wva/sia/e1'
job_name=cut_name(job_name) # e.g. 'ws1'
[...]
В форме сценария как, что Вы просите:
#!/usr/bin/env python3
import sys
# read the input, split by /
st = sys.argv[1].split("/")
# get the first char of all sections *but* the last one
# add the last *from* the first character
print("".join([s[0] for s in st][:-1])+st[-1][1:])
Обратите внимание, что это работает на любую длину, например:
wva/sia/bct/wva/sia/e1
станет
wsbws1
пока последний раздел заканчивается /e<num>
rearrange.py
Выполните его со строкой как аргумент, например:
python3 /path/to/rearrange.py wva/sia/e1
> ws1
Сценарий в значительной степени объясняется, но также и прокомментирован.
Позвольте нам просто сказать, что нам не нужен полный сценарий. Bash имеет достаточно возможностей, которые позволяют нам сходить с рук острота. Вот тот:
bash-4.3$ (read -r var ;IFS='/'; printf "%c" ${var%/*};echo ${var##*[^0-9]}) <<< "sv/de/e11"
sd11
Что происходит?
( )
вокруг целой команды<<<
отправить вход и команду подоболочки получает его через read -r var
и хранилища в var
переменнаяIFS='/'
так, чтобы подоболочка повредилась var
в отдельные объекты в /
разделитель. Это важно для разделения слова.${var%/*}
избавиться от последней части прежде /
. В вышеупомянутом примере это было бы e11
printf "%c"
будет видеть результат ${var%/*}
как sv de
из-за разделения слова и суффиксного упомянутого выше удаления (волшебство, да). Из-за как printf
слова, %c
распечатает только первый символ, но он сделает так для каждого параметра командной строки, для которого он получает, таким образом, sv de
это произведет s
и d
. Печать сделана без новой строки, следовательно появляется, как будто символы вводятся в последовательностиecho ${var##*[^0-9]}
использует удаление префикса для избавлений от всех символов нецифры в данной входной строке, таким образом получая только последние цифрыСуществует другой подход остроты, который является немного более явным и естественным для подобных C программистов.
bash-4.3$ (read -r inp;IFS='/';arr=( $inp ); for ((i=0;i<$(( ${#arr[@]} -1 ));i++));do printf "%s" ${arr[$i]:0:1};done;printf "%s\n" ${inp##*[^0-9]}) <<< "sv/de/e11"
sd11
Что это волшебно? Вот объяснение:
()
вокруг целой команды.<<<
для отправки объекта, мы хотим в stdin поток команды, и команда получает его через read -r inp
команда и хранилища это в inp
переменнаяIFS
переменная так, чтобы мы могли сломать все в массив.for ((initial condition; test condition; post condition)) ; do ... done
$(( ${#arr[@]} - 1 ))
арифметическое расширение, где мы вычитаем 1 из длины массива ${#arr[@]}
printf "%s" ${arr[$i]:0:1}
позволяет нам использовать расширение параметра, где мы печатаем только первый символ каждого объекта, и printf "%s"
печать это без новой строки, таким образом это появляется как, мы печатаем каждую букву на той же строке.${#*[^0-9]}
Так как вопрос просит сценарий оболочки, вот один в bash
4.3, который является почти тем же подходом как выше, но более явный:
#!/bin/bash
IFS='/'
items=( $1 )
counter=1
for i in ${items[@]}
do
if [ $counter -eq ${#items[@]} ];
then
# note the space before -1
printf "%s\n" "${i##*[^0-9]}"
else
printf "%s" "${i:0:1}"
fi
counter=$(($counter + 1))
done
Путем это работает, похож так:
/
, и позвольте удару выполнять разделение слова для разрушения строки в названный массив items
${items[@]}
, при отслеживании, которого объекта мы при использовании переменной счетчика и знании количества объектов в массиве ( ${#items[@]}
часть).if-statement
то, что позволяет нам выбирать определенный символ от каждого объекта. Используя расширение параметра, первый символ через${i:0:1}
. Используя самое долгое удаление префикса ${variable##prefix}
, мы удаляем все символы нецифры из последней строки в printf "%s\n" "${i##*[^0-9]}"
.Здесь это в действии:
$ ./shorten_string.sh "wva/sia/e1"
ws1
$ ./shorten_string.sh "bct/e2"
b2
$ ./shorten_string.sh "sv/de/e11"
sd11
Хорошо, не сценарий, но можно поместить его в сценарий (также это очень неэлегантно, так как мне не удалось иметь дело с обеими формами в одной команде),
$ sed -r 's:(.).*/(.).*/e([0-9]+):\1\2\3:;s:(.).*/e([0-9]+):\1\2:' file
ws1
b2
sd11
-r
используйте ДОs:old:new:
замена old
с new
.*
любое количество любых символов(.)
сохраните один символ в этом положении([0-9]+)
сохраните по крайней мере одну цифру здесь;
разделяет команды, как в оболочке\1
обратная ссылка на символы, сохраненные с ()