Що% робить у рядках оболонки Linux?


27

У Linux shell, що робить%, як у:

for file in *.png.jpg; do
  mv "$file" "${file%.png.jpg}.jpg"
done

4
Кожен раз, коли я дивлюся на це, я зазвичай знаходжу потрібний розділ сторінки bash man, шукаючи %%або ##, оскільки це запам'ятовується і досить рідко, щоб швидко знайти потрібний розділ. man bash /##
Пітер Кордес

3
@PeterCordes Я завжди пам’ятаю це за допомогою "Це 5%, тому% знаходиться в кінці і, таким чином, скорочується з кінця. І це # 5, тому # знаходиться на старті, а скорочується з початку". Але іноді я навіть змішую це…
glglgl

2
@glglgl: На типовій клавіатурі США #знаходиться відразу ліворуч $і %відразу праворуч. Не потрібні мнемічні --- просто дивіться вниз. (Мабуть, принаймні частина того, чому саме ці символи були вибрані.)
Кевін Дж. Чейз

@ KevinJ.Chase Не у всьому світі є типова клавіатура США. Але дійсно, на німецькій клавіатурі% - це теж $ $, що може стати початком для запам'ятовування.
glglgl

Відповіді:


29

Коли %використовується в шаблоні, ${variable%substring}він поверне вміст variableз найменшою швидкістю substringвидалення зі зворотної сторони variable.

Ця функція підтримує шаблони підстановки - тому вона приймає зірочку (зірочку) як підміст для нуля або більше символів.

Слід зазначити, що це специфічно для Bash - інші оболонки Linux не обов'язково містять цю функцію.

Якщо ви хочете дізнатися більше про обробку рядків у Bash, я настійно пропоную прочитати цю сторінку. Серед інших зручних функцій він, наприклад, пояснює, що робить %%:)

Змінити: Я забув згадати , що , коли він використовується в шаблоні $((variable%number))або персонаж буде функціонувати в якості оператора по модулю. DavidPostill має більш конкретні посилання на документацію у своїй відповіді.$((variable1%$variable2))%

Якщо %він використовується в іншому контексті, його слід визнавати лише регулярним символом.


2
Оператор підтримує шаблони підстановки , а не регулярні вирази.
садок

Як і згадуваний садок - він підтримує глобальні візерунки, а не регулярні вирази. У регулярному виразі зірка означає нуль або більше попереднього символу.
slebetman

5
Посібник, з яким ви пов’язані, дуже не рекомендується більшістю користувачів обміну стеками Unix & Linux . Я рекомендую замість цього посібник Wooledge Bash .
Wildcard

3
Оператори видалення префіксів та суфіксів є стандартними , тому вони повинні бути використані в будь-якій shсумісній оболонці, не тільки Bash. (хоча, можливо, не в cshтому подібному).
ilkkachu

1
Інший контекст, в якому %використовується, є у специфікаторах формату для printf.
Денніс Вільямсон

9

Довідковий посібник Bash: Розширення параметрів оболонки

${parameter%word}
${parameter%%word}

Слово розкривається , щоб отримати шаблон так само , як в розширенні імені файлу. Якщо візерунок збігається з кінцевою частиною розширеного значення параметра , то результатом розширення є значення параметра з найкоротшим шаблоном відповідності ( ‘%’випадок) або найдовшим шаблоном збігу ( ‘%%’випадок), видаленим. Якщо параметр є ‘@’або ‘*’,операція з видалення шаблону застосовується по черзі до кожного позиційного параметра, а розширення є списком результатів. Якщо параметр є змінною масиву, підписаний на ‘@’ або‘*’, операція видалення шаблону застосовується по черзі до кожного члена масиву, а розширення - це результат списку.


2
Зверніть увагу: деякі розширення параметрів, включаючи%, є функціями posix, які підтримує багато оболонок.
kojiro

7

Експериментуючи, я виявляю, що відповідність після% відміняється, коли рядок укладається у фігурні дужки (дужки).

Проілюструвати:

touch abcd         # Create file abcd

for file in ab*; do
 echo $file        # echoes the filename
 echo $file%       # echoes the filename plus "%"
 echo ${file%}     # echoes the filename
 echo "${file%}"   # echoes the filename
 echo
 echo "${file%c*}" # Discard anything after % matching c*
 echo "${file%*}"  # * is not greedy
 echo ${file%c*}   # Without quotes works too
 echo "${file%c}"  # No match after %, no effect
 echo $file%c*     # Without {} fails
done

Ось вихід:

abcd
abcd%
abcd
abcd

ab
abcd
ab
abcd
abcd%c*

7

Що в оболонці Linux ( bash), що %робити?

for file in *.png.jpg; do
  mv "$file" "${file%.png.jpg}.jpg"
done

В даному конкретному випадку, %це зіставлення з зразком оператор (зверніть увагу , це також може бути по модулю оператор).


Оператор відповідності шаблонів

$ {var% $ Pattern}, $ {var %% $ Pattern}

${var%$Pattern}Видаліть із $varнайкоротшої частини, $Patternяка відповідає задній частині $var.

${var%%$Pattern}Вийміть із $varнайдовшої частини, $Patternяка відповідає задній частині $var.

Приклад: Узгодження шаблону при заміні параметрів

#!/bin/bash
# patt-matching.sh

# Pattern matching  using the # ## % %% parameter substitution operators.

var1=abcd12345abc6789
pattern1=a*c  # * (wild card) matches everything between a - c.

echo
echo "var1 = $var1"           # abcd12345abc6789
echo "var1 = ${var1}"         # abcd12345abc6789
                              # (alternate form)
echo "Number of characters in ${var1} = ${#var1}"
echo

echo "pattern1 = $pattern1"   # a*c  (everything between 'a' and 'c')
echo "--------------"
echo '${var1#$pattern1}  =' "${var1#$pattern1}"    #         d12345abc6789
# Shortest possible match, strips out first 3 characters  abcd12345abc6789
#                                     ^^^^^               |-|
echo '${var1##$pattern1} =' "${var1##$pattern1}"   #                  6789      
# Longest possible match, strips out first 12 characters  abcd12345abc6789
#                                    ^^^^^                |----------|

echo; echo; echo

pattern2=b*9            # everything between 'b' and '9'
echo "var1 = $var1"     # Still  abcd12345abc6789
echo
echo "pattern2 = $pattern2"
echo "--------------"
echo '${var1%pattern2}  =' "${var1%$pattern2}"     #     abcd12345a
# Shortest possible match, strips out last 6 characters  abcd12345abc6789
#                                     ^^^^                         |----|
echo '${var1%%pattern2} =' "${var1%%$pattern2}"    #     a
# Longest possible match, strips out last 12 characters  abcd12345abc6789
#                                    ^^^^                 |-------------|

# Remember, # and ## work from the left end (beginning) of string,
#           % and %% work from the right end.

echo

exit 0

Джерело Параметр Заміна


Оператор модуля

%

modulo або mod (повертає залишок цілочисельної операції поділу)

bash$ expr 5 % 3
2

5/3 = 1, а решта 2

Оператори джерела


Можливо, я це зрозумів: це для таких речей .*і %визначає, що це не жадібно, тоді як %%робить це жадібним? Так на самому справі в прикладі перейменування не має значення , слід використовувати %або , %%але якщо б це було mv "$file" "${file%.*png.jpg}.jpg"(зверніть увагу на *) , використовуючи %% буде перейменувати всі файли просто .jpg, НЕ так?
Томас Веллер

@ThomasWeller Я думаю, що це правильно. Але я не фахівець з басу.
DavidPostill

Вислів «Видалити ... найкоротша частина $Pattern» не так , як змінна $Patternне визначена в прикладі, тільки текст «Візерунок» видаляється з $varколи робити ${var%Pattern}або ${var%%Pattern}. Можливо, це просто помилка, але це ще один приклад того, що tldp.org помиляється. BashGuide або Bash Hackers Wiki - це набагато кращі посилання.
Джон Б

@JohnB Дякую Обидва посилання закладені в закладки. Я виправив текст у відповіді.
DavidPostill
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.