Зацикливание выделенного файла табуляции в скрипте 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

у меня не получается, если какое-либо из полей содержит пробелы
v01pe

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

readIFSпо умолчанию разделяет поля, разделенные символами, в значении переменной, которая состоит из пробела и табуляции (плюс новая строка, которая не может быть внутри строки). Чтобы разделить только вкладки, IFSсначала выберите одну вкладку. Обратите внимание, что ведущие и конечные вкладки игнорируются, а последовательные вкладки учитываются как одна.

read лечит \ как специальный символ: обратный слеш, за которым следует новая строка, игнорируются; \\становится одиночной обратной косой чертой. Если вы хотите избежать такого поведения, передайте -rопцию.


15
+1. Чтобы установить МФС на вкладку полукокса в Баш:IFS=$'\t'
Glenn Джекман
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.