Замініть один символ на інший у Bash


223

Мені потрібно вміти замінити пробіл ( ) на крапку ( .) в рядку в bash.

Я думаю, що це було б досить просто, але я новий, тому не можу зрозуміти, як змінити подібний приклад для цього використання.

Відповіді:


390

Використовуйте заміну рядкових оболонок. Приклад:

foo="  "

# replace first blank only
bar=${foo/ /.}

# replace all blanks
bar=${foo// /.}

Докладнішу інформацію див. У розділі http://tldp.org/LDP/abs/html/string-manipulation.html .


1
Хоча це рішення добре при роботі з короткими рядками (звичайний випадок, я думаю) можна віддавати перевагу trдовгим рядкам. У моїй системі trперевершує баш, починаючи з рядків, що мають більше 1000символів. Схоже, складність у часі Баша гірша, ніж лінійна. Невеликий тест: x="$(tr -dc 'a-z \n' </dev/urandom | head -c1M)"; time y="$(tr ' ' \\- <<< "$x")"; time z="${x// /-}". З довжиною струни 1М (= 2 ^ 20) trвзяв 0.04sі баш 5,0,11 взяв 17s. З 2M trвзяли 0.07s(очікувалося), але беш брали 69s(4 рази більше, ніж удвічі довше струни).
— Socowi

@Socowi Гра з 1 Мб, що зберігається в змінній, насправді не звичайна! До 10 Кбіт баш здається, що швидше залишається швидшим, ніж роздрібнювати tr! ... Залежно від наявної пам’яті та ресурсів hw ... Але ви праві!
— Ф. Хаурі

Для втікаючих персонажів, таких як нові рядки, обов’язково шукайте$'\n'
— user2561747,

75

Ви можете використовувати tr, як це:

tr " " .

Приклад:

# echo "hello world" | tr " " .
hello.world

Від man tr:

ОПИС
     Перекладіть, видавіть та / або видаліть символи зі стандартного вводу, починаючи із стандартного виводу.


Хоча це працює на запитання, як було задано, він менш загальний, ніж прийнятий відповідь (який працює на заміну символів, а також довільних рядків), а також включає і зовнішнє командування.
— Дан Даскалеску

2
З іншого боку, він працює на 2gb-файлі без завантаження всієї речі в пам'ять.
— aioobe

Питання стосувалося "рядка в баші", а не довільно великих файлів.
— Дан Даскалеску

52

У bash ви можете зробити заміну шаблону в рядку з ${VARIABLE//PATTERN/REPLACEMENT}конструкцією. Використовуйте просто, /а не //замінювати лише перше виникнення. Візерунок - це підстановочний шаблон, як файлові кулі.

string='foo bar qux'
one="${string/ /.}"     # sets one to 'foo.bar qux'
all="${string// /.}"    # sets all to 'foo.bar.qux'



4

Спробуйте це для шляхів:

echo \"hello world\"|sed 's/ /+/g'|sed 's/+/\/g'|sed 's/\"//g'

Він замінює простір всередині подвійного цитування рядка +співом, потім замінює +знак зворотною косою рисою, потім видаляє / замінює подвійні лапки.

Мені довелося використовувати це для заміни пробілів на одному зі моїх шляхів у Cygwin.

echo \"$(cygpath -u $JAVA_HOME)\"|sed 's/ /+/g'|sed 's/+/\\/g'|sed 's/\"//g'

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