Какова концепция наименьшего совпадения подстрок в Unix Shell?

Я использую следующий скрипт для Shortest Sub-string Match в обработке строк.

filename="bash.string.txt" echo ${filename#*.} 

Это дает следующий вывод.

 string.txt 

Вот объяснение приведенного выше примера (ссылка: https://www.thegeekstuff.com/2010/07/bash-string-manipulation ):

Приведенный выше пример удаляет самое короткое совпадение $ substring с начала $ string. В первом эхо-запросе подстрока ‘*.’ сопоставляет символы и точку, и # удаляет из начала строки, поэтому она удаляет подстроку «bash.» из переменной с именем filename.

Затем я изменил код, как показано ниже:

 filename="bashshell.string.txt" echo ${filename#*.} 

Я только что расширил первую строку из bash. перебить и ожидая вывода «bashshell.txt» в соответствии с объяснением, приведенным выше. Но вместо этого он дает мне тот же результат, что и в первом примере.

то есть string.txt

Так я неправильно понял концепцию? Если да, то как это на самом деле работает?

Так я неправильно понял концепцию? Если да, то как это на самом деле работает?

Да, запись ${var#*.} Удаляет все, начиная с начала строки и заканчивая точкой символа ( . ). Он делает то, что вы просили, ваш шаблон был звездной точкой:

 *. 

Таким образом, он будет соответствовать всему, вплоть до 1-й точки от начала строки, которая следует за словом bash .

 bash.string.txt ^---------------- it's splitting here 

Примеры

 $ str="bash.string.txt" $ echo "${str#*.}" string.txt $ str="bash1.string.txt" $ echo "${str#*.}" string.txt $ str="bash1.string1.txt" $ echo "${str#*.}" string1.txt 

Смотрите, когда я ставлю 1 на левой стороне 1-го . , Эта запись сокращает все до 1-й точки.

Использование в учебнике слова «подстрока» немного вводит в заблуждение. При использовании ${variable#pattern} мы имеем дело с сопоставлением и удалением строки префикса (а с ${variable%pattern} строкой суффикса ).

Вы удалили кратчайший префикс соответствия строки *. из двух строк bash.string.txt и bashshell.string.txt . Результат для обеих строк одинаков, string.txt , потому что шаблон *. соответствует до и включая первую точку в строке.

Стандарт POSIX определяет это расширение конкретного параметра как

${parameter#[word]}

Удалите самый маленький образец префикса. Слово должно быть расширено, чтобы произвести образец . Расширение параметра должно затем привести к параметру с наименьшей частью префикса, совпадающей с удаленным шаблоном . Если присутствует, слово не должно начинаться с # без кавычек.

Если бы вы хотели получить результат bashshell.txt , вам пришлось бы удалить строку .string или string. с середины строки. Это можно сделать в два этапа со стандартными расширениями параметров:

 suffix=${filename##*.} # remove everything to the *last* dot echo "${filename%%.*}.$suffix" # remove everything from the first dot and add suffix 

## и %% расширения параметра удаляют самые длинные совпадающие строки префикса и суффикса соответственно.

Альтернативно с bash :

 echo "${filename/string./}" 

Это удаляет (первое вхождение) заданную строку в любом месте значения $filename .