Як уникнути спеціальних символів у рядку?


16

Скажімо, $fileутримуючи значення імені файлу, скажімо Dr' A.tif. Як баш програмування, як я можу уникнути однієї цитати та будь-якого іншого спеціального символу $fileбез усунення спеціального символу?

Оновлення 9 липня 2014 року

Як запит від @Gilles , наступний фрагмент коду, який не вдається обробити Dr' A.tif:

files=$(find /path/ -maxdepth 1 -name "*.[Pp][Dd][Ff]" -o -name "*.[Tt][Ii][Ff]")
echo "${files}" > ${TEMP_FILE}
while read file
do
   newfile=$(echo "${file}" | sed 's, ,\\ ,g') ## line 1
done < ${TEMP_FILE}

Після того, як я випробував в відповідь від @Patrick на line 1, здається, працює для мене. Але якщо у мене є такий файл, як Dr\^s A.tif, printfкоманда, здається, не допомагає, він мені показує Dr\^s\ A.tif. Якщо я вручну спробую це на консолі так:

printf "%q" "Dr\^s A.tif"

У мене буде такий вихід:

Dr\\\^s\ A.tif

Будь-яка ідея, як впоратися з цим?


3
в якому контексті ви розраховуєте використовувати файл $? чи це питання присвоює рядок зі спеціальним символом файлу $?
пограбувати

Насправді команда find повертає мені масив списку файлів. А потім я перебираю цей список файлів у змінну $ file.
huahsin68

2
Тут вам дали правильні відповіді, але вони, мабуть, не є відповідями на питання, яке ви справді задаєте. З вашого коментаря тут я сильно підозрюю, що ви не в тому напрямку. Ми не можемо вам допомогти, тому що ви постійно не показуєте код. Однак я рекомендую вам ознайомитися. Чому мій скрипт оболонки задихається на пробілі чи інших спеціальних символах? як тло. Покажіть свій сценарій і поясніть, що ви хочете зробити.
Жил "ТАК - перестань бути злим"

Відповіді:


14

Ви можете використовувати printfвбудований, %qщоб досягти цього. Наприклад:

$ file="Dr' A.tif"
$ printf '%q\n' "$file"
Dr\'\ A.tif

$ file=' foo$bar\baz`'
$ printf '%q\n' "$file"
\ foo\$bar\\baz\`

З документації bash на printf:

In addition to the standard format specifications described in printf(1)
and printf(3), printf interprets:

 %b       expand backslash escape sequences in the corresponding argument
 %q       quote the argument in a way that can be reused as shell input
 %(fmt)T  output the date-time string resulting from using FMT as a format
          string for strftime(3)

Це не працює в певних випадках. Наприклад, коли вам потрібно зберегти подвійні лапки.
користувач3467349

@ user3467349 це працює чудово з цитатами. Б'юсь об заклад, що ви намагаєтесь щось подібне printf '%s' "foo". Потрібно зрозуміти, як спочатку працює аргумент в оболонці. Дивіться сторінку gnu.org/software/bash/manual/bash.html#Shell-Operation # 2 відбувається до №6.
Патрік

Чи можете ви надати приклад цього рядка, надрукованого з printfіншими маніпуляціями та жодних інших маніпуляційIt doesn't have a: ""
user3467349

Ваше питання не має нічого спільного printf. Ваша проблема полягає в тому, що ви не хочете, щоб оболонка розбирала рядок. Для цього вам потрібно передати свій вхід в оболонку таким чином, щоб він навіть не намагався її розібрати. Одним із способів зробити це було б read -r -p 'input: ' && printf '%q\n' "$REPLY"і надати вхід, коли буде запропоновано.
Патрік

1
Як я вже говорив кілька разів. Не знаючи, як передати необроблені дані в оболонку, це не проблема printf. Можливо, вам слід задати питання, а не критикувати рішення, яке не має нічого спільного з вашою проблемою.
Патрік

4

Спробуйте: -

file=Dr\'\ A.tif
echo $file
Dr' A.tif

або

file="Dr' A.tif"
echo $file
Dr' A.tif

або якщо рядок містить подвійну лапочку: -

file='Dr" A.tif'
echo $file
Dr" A.tif

Є хороші підручники щодо втечі та цитування в мережі. Почніть з цього .


1

Вам не потрібно уникати імен файлів, якими ви обробляєте сценарій. Утеча необхідна лише в тому випадку, якщо ви хочете помістити ім'я файлу як буквальне в сценарій, або передати кілька імен файлів як один потік введення до іншого сценарію.

Оскільки ви пробираєтеся через висновок find, це один з найпростіших способів (!) Обробити кожен можливий шлях :

while IFS= read -r -d ''
do
    file_namex="$(basename -- "$REPLY"; echo x)"
    file_name="${file_namex%$'\nx'}"
    do_something -- "$file_name"
done <(find "$some_path" -exec printf '%s\0' {} +)


-1

Багато з цих відповідей, включаючи те, хто використовує голосів, не printf "%q"будуть працювати у всіх випадках без додаткових маніпуляцій. Я б запропонував таке (приклад нижче):

cat <<EOF; 2015-11-07T03:34:41Z app[postgres.0000]: [TAG] text-search query doesn't contain lexemes: "" EOF


Вибачте питання n00b, але чи можете ви детальніше розповісти про те, як би ви насправді використовували це для втечі символів у рядку? Якщо я скопіюю код, який ви записуєте в мій термінал, він просто надрукує 2015-11-07T03: 34: 41Z додаток [postgres.0000]: [TAG] Текстовий запит не містить лексеми: "" ... нічого не уникнути .
SharkAlley

Це буквально точка, всі спеціальні символи будуть інтерпретуватися як літерні символи не для їх особливого сенсу. Спробуйте повторити "вищезазначений рядок" замість цього, щоб побачити різницю.
користувач3467349
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.