awk: извлечь столбцы с разделителями табуляции, соответствующие подстрокам в первой строке

Справочная страница для PKGBUILD описывает, как использовать источники управления версиями. Хотя makepkgизначально поддерживает источники git, он не предоставляет простых средств предоставления опций для git. Хотя можно изменить makepkg.conf, как я предложил в этом ответе , чтобы переопределить поведение gitпо умолчанию или указать собственный dlagent/vcsclient, справочную страницу для PKGBUILD предлагает:

For other version control systems, manual cloning of upstream repositories must be done in the prepare() function.

Другими словами, не добавляйте репозиторий git в массив sources, а делайте все в функции prepare.

1
27.05.2019, 17:36
5 ответов

Изменение моего решения для вашего предыдущего вопроса:

awk -F '\t' -f script.awk strings.txt columns.txt

где script.awkэто

BEGIN { OFS = FS }

FNR == NR {
    columns[$1] = 1
    next
}

FNR == 1 {
    for (i = 1; i <= NF; ++i)
        if ($i in columns)
            keep[i] = 1
}

{
    nf = split($0, fields, FS)
    $0 = ""
    j = 0

    for (i = 1; i <= nf; ++i)
        if (i in keep)
            $(++j) = fields[i]

    print
}

Здесь блок FNR == NRбудет выполняться только при чтении из первого файла, указанного в командной строке(strings.txt). Массив columnsбудет заполнен ключами, являющимися именами столбцов. Остальной код более или менее не изменился по сравнению со старым решением, за исключением того, где мы проверяем, является ли текущий столбец тем, который мы хотели бы сохранить (в блоке FNR == 1). ].


Ответы на вопросы в комментариях:

Чтобы всегда копировать первые шесть столбцов и вырезать заголовки столбцов в _, измените

FNR == 1 {
    for (i = 1; i <= NF; ++i)
        if ($i in columns)
            keep[i] = 1
}

в

FNR == 1 {
    for (i = 1; i <= NF; ++i) {
        sub("_.*", "", $i)
        if (i <= 6 || $i in columns)
            keep[i] = 1
    }
}
1
27.01.2020, 23:14

Скрипт очень сложный (т.е. awkнеобходимость )или ваши данные очень большие? Вы можете использовать datamashдля транспонирования вашего файла данных, grepстолбцы (теперь строки )с файлом строк и повторно транспонировать:

datamash transpose < in.txt  | grep -f strings.txt  | datamash transpose > out.txt

Подобным образом вы также можете получить не соответствующие -столбцы:

datamash transpose < in.txt  | grep -f strings.txt -v  | datamash transpose > out.txt

РЕДАКТИРОВАТЬ:

Так как вы работаете с очень большим файлом, cutможет помочь :первая (заголовков )строка ваших данных преобразуется в одну строку на заголовок, grepвыбирает строку числа, соответствующие strings.txtзаписям, и, таким образом, у нас есть поля (столбца )числа, необходимые для cut, которые затем повторно преобразуются в значения, разделенные запятыми -для выбора поля cut.

cut -f $( grep -n -f strings.txt <( head -1 data.txt | tr '\t' '\n' ) \|
   sed 's/:.*//' | tr '\n' ',' | sed 's/,$//' ) data.txt 

Снова -несоответствующие столбцы возникают из-за использования grep -v.

0
27.01.2020, 23:14

Сperl

$ perl -F'\t' -lane 'if(!$#ARGV){ $h{$_}=1 }
                     else{ @i = grep { $h{$F[$_]} == 1 } 0..$#F if !$c++;
                           print join "\t", @F[@i]}' strings.txt columns.txt
rs2438689   rs9877702046
0   0
1   2
0   2
  • if(!$#ARGV){ $h{$_}=1 }для первого входного файла создайте хеш со строковым содержимым в качестве ключа
  • @i = grep { $h{$F[$_]} == 1 } 0..$#F if !$c++для первой строки второго файла создайте индексный список всех совпадающих имен столбцов из хэша
  • print join "\t", @F[@i]вывести соответствующие столбцы
2
27.01.2020, 23:14

Вместо Awk, как насчет того, чтобы составить разделенный запятыми -список имен столбцов из strings.txtи использовать его как список из namedcolдляcsvtool:

$ csvtool -t TAB -u TAB namedcol "$(paste -sd, < strings.txt)" columns.txt
rs2438689   rs9877702046
0   0
1   2
0   2
......

или аналогично csvcut/csvformatиз Python -на основеcsvkit:

$ csvcut -tc "$(paste -sd, < strings.txt)" columns.txt | csvformat -T
rs2438689   rs9877702046
0   0
1   2
0   2
......
3
27.01.2020, 23:14

Сделано с помощью приведенного ниже скрипта, возможно, он долго работал нормально

к=wc -l file1| awk '{print $1}'

for ((i=1;i<=$k;i++));  do for j in `cat file2`; do awk -v i="$i" -v j="$j" '$i == j {x=NR+k}(NR<=x){print $i}' file1; done ; done>final.txt

z=`wc -l final.txt| awk '{print $1}'`

for ((i=1;i<=$z;i++)); do j=$(($i+3)); sed -n ''$i','$j'p' final.txt >file_starting_with_$i.txt; i=$j; done

paste file_starting_with*

выход

rs2438689   rs9877702046
0       0
1       2
0       2
0
27.01.2020, 23:14

Теги

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