2015-04-04 4 views
0

У меня есть файл TSV, где каждая строка представляет аргументы командной строки и командной строки. Пример:Выполнять команды и аргументы из файла TSV

ls  ~ 
cd  /home 
cp  dir1 dir2 

Каждая строка может иметь переменное количество столбцов. Каждая ячейка может содержать пробелы, одинарные кавычки и двойные кавычки.

Что такое хороший способ выполнить это?

+1

'Баш filename' – ShellFish

+0

@ShellFish близко, но если ячейка имеет в нем пробелы, тогда они будут рассматриваться как отдельные аргументы. Я также попробовал '(IFS = $ '\ t'; source load.tsv)' –

+1

Да, это был не ответ, а указатель, поэтому комментарий. Сначала сделайте 'sed -i s// \\/g'. – ShellFish

ответ

1

Использование Bash, прочитать в массив с МФС, установленным на вкладке:

$ cat data 
ls  ~ 
cd  /home 
cp  dir1 dir2 
al  a b  c d 
$ vis -t -n data 
ls^I~^J 
cd^I/home^J 
cp^Idir1^Idir2^J 
al^Ia b^I c d ^J 
$ while IFS=$'\t' read -r -a xyz; do al "${xyz[@]}"; done < data 
ls 
~ 
cd 
/home 
cp 
dir1 
dir2 
al 
a b 
    c d 
$ while IFS=$'\t' read -r -a xyz; do al "${xyz[@]}"; done < data | vis -t -n 
ls^J 
~^J 
cd^J 
/home^J 
cp^J 
dir1^J 
dir2^J 
al^J 
a b^J 
    c d ^J 
$ 

vis программа с опциями -t -n печатает вкладки как ^I и новой строки как ^J (с последующим переводом строки); программа al печатает свои аргументы по одной в строке - она ​​фактически эквивалентна printf "%s\n" "[email protected]" (это на самом деле очень простая программа на C, но результат тот же).

С реальными командами в файл, чтобы быть выполнен, вы бы написать:

while IFS=$'\t' read -r -a xyz; do "${xyz[@]}"; done < data 

На моей машине, я получил:

$ (while IFS=$'\t' read -r -a xyz; do "${xyz[@]}"; done < data) 
ls: ~: No such file or directory 
cp: dir1: No such file or directory 
a b 
    c d 
$ 

Я использовал подоболочку, потому что я Жду» t хочу оставить мой текущий каталог в моей основной оболочке, и у меня нет dir1 для копирования в dir2. Обратите внимание, что оболочка не делала расширения тильды по результатам расширения параметра, поэтому ls получил, чтобы увидеть фактическую тильду, а не значение моего домашнего каталога. Крепление расширения тильды было бы болезненным - мучительно болезненным (см. Tilde expansion in quotes). Это также означает, что нотация диапазона, такая как {1..10}, не будет расширяться и что псевдонимы не будут расширены. См. Shell expansions, что бы и не произошло.

+0

Это отлично работает! –

+0

На самом деле это не работает, если один из аргументов пуст. Кроме того, не работает с zsh –

+0

Любая последовательность из одной или нескольких вкладок рассматривается как отдельный разделитель аргументов. Вы не упомянули 'zsh' в вопросе; тегами являются [tag: bash] и [tag: xargs]. Вы знаете, почему это не работает в 'zsh'? Если вам нужны пустые поля, то вам, безусловно, придется изменить этот ответ; вы, вероятно, не сможете это сделать с оболочкой и IFS. –

0

Решение:

ruby -ne 'require "shellwords"; system $_.chomp.split("\t").shelljoin' 

Доказательство:

Вот наше тестирование сценария: cat printArguments.bash:

#!/bin/bash 
args=("[email protected]") 
for ((i=0; i < $#; i++)) { 
    echo "argument $((i+1)): ${args[$i]}" 
} 

И тест:

echo $'./printArguments.bash\t1\t\t3' | ruby -ne 'require "shellwords"; system $_.chomp.split("\t").shelljoin' 

Результат:

Аргумент 1: 1

Аргумент 2:

Аргумент 3: 3

Смежные вопросы