Проведіть цикл, розмічений на вкладці, у файлі bash


18

Ось що я маю досі:

#!/bin/bash
while read line; do
        DB=$(echo $line | cut -f1)
        USER=$(echo $line | cut -f2)
        PASS=$(echo $line | cut -f3)
        echo DB=$DB USER=$USER PASS=$PASS
done < users.txt

І зразок вхідного файлу:

drupal_1    drupal1 tmmjXSWL
drupal_2    drupal2 FHiJSYHM
drupal_3    drupal3 b7bFNj06
drupal_4    drupal4 0AaV62EL

І вихід із сценарію:

DB=drupal_1 drupal1 tmmjXSWL USER=drupal_1 drupal1 tmmjXSWL PASS=drupal_1 drupal1 tmmjXSWL
DB=drupal_2 drupal2 FHiJSYHM USER=drupal_2 drupal2 FHiJSYHM PASS=drupal_2 drupal2 FHiJSYHM
DB=drupal_3 drupal3 b7bFNj06 USER=drupal_3 drupal3 b7bFNj06 PASS=drupal_3 drupal3 b7bFNj06

Чомусь кожна змінна встановлюється на весь рядок. Коли я використовую echo users.txt | cut -f1в командному рядку, він повертає маркер просто чудово.

Відповіді:


6

Як щодо цього?

$ awk '{print "DB="$1"\tUSER="$2"\tPASS="$3}' users.txt
DB=drupal_1 USER=drupal1    PASS=tmmjXSWL
DB=drupal_2 USER=drupal2    PASS=FHiJSYHM
DB=drupal_3 USER=drupal3    PASS=b7bFNj06
DB=drupal_4 USER=drupal4    PASS=0AaV62EL

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


Дякую, це працює. Я намагаюся написати сценарій для створення 40+ інсталяцій Drupal на сервері для класу, який я викладаю. У мене є сценарії для налаштування БД і файлів, це фрагмент сценарію, який зведе все це. Проблема мого коду полягала в тому, що рядок $ перетворила вкладки на пробіли під час їх розбору. $(echo $line | cut -d" " -f1)також працює.
mortona42


21

Проблема в команді echo $line. Оскільки лапок навколо немає $line, оболонка виконує розбиття слів на ньому, а потім інтерпретує кожне слово як глобульний шаблон. Спробуйте це

a='*.txt foo'
ls $a

У вашому випадку вкладки розділяють слова, які потім стають окремими аргументами echo. echoКоманда друкує аргументи розділені пропуском. Таким чином cutотримує поле, обмежене пробілом, замість полів з обмеженими пробілами.

Завжди ставити подвійні лапки навколо змінних підстановок $fooі підстановок команд$(foo) (якщо ви не розумієте, для чого вам потрібно залишати їх і чому це нормально). echo "$line"працювали б тут, але це складний спосіб робити те, що ви пропонуєте.

Зберігаючи підхід до розбору в оболонці, ви можете зробити readкоманду для розбору введення в поля.

while read DB USER PASS; do
  echo "DB=$DB USER=$USER PASS=$PASS"
done <users.txt

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

readтрактує \як особливий персонаж: зворотний проріз, який супроводжується новим рядком, ігнорується; \\стає єдиним зворотним нахилом. Якщо ви хочете уникнути такої поведінки, перейдіть до цього -rваріанту.


15
+1. Щоб встановити IFS на IFS=$'\t'
таблицю
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.