Извлечь части файла csv в столбцы

Решение, которое не требует цикла в оболочке:

awk 'pass==1 {  Xpatt[NR] = $1; Yfile[NR] = $2 ".dat"; printf "" > Yfile[NR] }
     pass==2 {
                for (i in Xpatt) {
                        if ($0 ~ Xpatt[i]) print $NF > Yfile[i]
                }
             }' pass=1 NAMES pass=2 results.dat
  • Прежде всего, awk позволяет вам указывать назначения переменных в качестве аргументов командной строки, {{1} } после программы, смешанные с именами файлов, без использования -v . Они выполняются в той точке последовательности обработки , которую предлагает их позиция в командной строке. Итак, в приведенной выше команде

    1. pass получает установлено значение 1,
    2. обрабатывается файл NAMES ,
    3. pass получает значение 2, а затем
    4. обрабатывается файл results.dat .

    Думаю, я мог бы установить pass = 1 с помощью -v или в блоке BEGIN .

    Я использую переменную pass , чтобы указать, какой файл я читаю. Обычно это делается путем сравнения NR с FNR , , но это может привести к ложным показаниям, если файл пуст.

    (Строго говоря, я полагаю, что этот сценарий должен проверять, является ли какой-либо из файлов пустым, потому что в этом случае работать не нужно.)

  • Хотя pass == 1 (мы читаем файл NAMES ), сохраняем значения X и Y (шаблон и имя файла) из столбцов 1 и 2 ( $ 1 и $ 2 ) этого файла. Создайте выходной файл ( Yfile [NR] ), потому что, если мы этого не сделаем здесь, мы не получим (пустые) выходные файлы {{1} } для шаблонов, которых нет в файле results.dat . (Если вас это устраивает, опустите инструкцию printf .)
  • Пока pass == 2 (мы читаем файл results.dat ), перебирает шаблоны в NAMES ] файл и выведите последнее слово из каждой строки, которая соответствует шаблону , в соответствующий файл - то есть, эквивалент OP grep X… | awk '{print $ NF}'> команда Y.dat .
2
05.07.2016, 12:03
2 ответа

Использование sed

$ printf "%s\n" * | sed 's/.csv$//; s/_/\t/g'
abc     q1      w1
defg    q11     w2
hijk    q11     w3

Как это работает:

  • printf "%s\n" * печатает имена файлов по одному в строке

  • s/.csv$// удаляет концевой .csv.

  • s/_/\t/g преобразует _ в табуляцию.

Использование bash

$ for f in *; do f="${f%.csv}"; printf "%s\n" "${f//_/$'\t'}";  done
abc     q1      w1
defg    q11     w2
hijk    q11     w3

Если это поможет прояснить ситуацию, вышеприведенный код можно разбить на несколько строк:

for f in *
do
    f="${f%.csv}"
    printf "%s\n" "${f//_/$'\t'}"
done

${f%.csv} удаляет идущие следом .csv и ${f//_/$'\t'} преобразует все _ в табуляции.

Мы не используем echo для этой задачи, потому что, если одно из имен файлов начинается с -, многие оболочки попытаются интерпретировать это имя файла как опцию, и результат будет не очень хорошим.

Запуск кода из другого каталога

$ for f in "$dir"/*; do f="${f#$dir/}"; f="${f%.csv}"; printf "%s\n" "${f//_/$'\t'}";  done
abc     q1      w1
defg    q11     w2
hijk    q11     w3
1
27.01.2020, 22:04

Вы можете использовать что-то вроде:

ls -1 | tr '_' '\t'
2
27.01.2020, 22:04

Теги

Похожие вопросы