Замініть один символ на інший у 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.