как запустить awk с определенного номера строки, хранящейся в переменной

Самым простым способом было бы скопировать весь архив; я предполагаю, что вы не хотите этого делать, потому что он слишком большой.

Обычные инструменты командной строки (tar, pax) не поддерживают копирование членов архива в другой архив.

Если вам не нужно сохранять право собственности, я бы предложил использовать файловые системы FUSE. Вы можете использовать archivemount для монтирования архива как файловой системы; сделайте это для исходного архива и запустите tar на смонтированной файловой системе.

archivemount some.tar.gz mnt
cd mnt
tar -cz subdir | ssh example.com tar -xz
fusermount -u mnt

В качестве альтернативы можно использовать AVFS:

mountavfs
cd ~/.avfs$PWD/some.tar.gz\#
tar -cz subdir | ssh example.com tar -xz

Также можно запустить tar на исходном архиве и извлечь на удаленную машину через SSHFS.

sshfs example.com: mnt
cd mnt
tar -xf /path/to/some.tar.gz subdir
fusermount -u mnt

Однако все эти методы громоздки, если вам нужно сохранить право собственности. Все они подразумевают извлечение в файл на локальной машине, поэтому права собственности на этот файл должны соответствовать предполагаемым удаленным правам собственности. Это требует запуска от имени root и может не дать желаемого результата, если файлы принадлежат учетным записям, имена или идентификаторы которых отличаются на локальной машине и удаленном хосте.

Библиотека tarfile Python предоставляет довольно простой способ манипулирования членами tar, так что вы можете перетасовывать их из одного tar-файла в другой. Она поддерживает стандартные форматы POSIX (ustar, pax), а также некоторые расширения GNU. Вот непроверенный сценарий Python, который читает tar-файл (возможно, сжатый gzip или bzip2) на стандартном входе и записывает tar-файл, сжатый bzip2, на стандартном выходе. Члены из источника копируются, если они начинаются с аргумента, переданного скрипту.

#!/usr/bin/env python2
import sys, tarfile
source = tarfile.open(fileobj=sys.stdin)
destination = tarfile.open(fileobj=sys.stdout, mode='w:bz2')
for info in source:
    if info.name.startswith(sys.argv[1]):
        destination.addfile(info)
destination.close()

Вызывается как

tar_filter 

1
08.03.2018, 16:31
3 ответа

No hagas esto en un bucle de shell, awklo hará por ti.

Este es un script awkque puede almacenar en un archivo de script e invocar conawk -f script.awk filename(modificado para trabajar con la edición reciente de la pregunta):

BEGIN {
        follows["foo"] = "bar"
        follows["bar"] = "foo"
}

{
        for (i = 1; i <= NF; ++i)
                if (lookfor == "") {
                        if ($i in follows)
                                lookfor = follows[$i]
                } else if ($i == lookfor) {
                        record[$i] = (record[$i] == "" ? "" : record[$i] OFS ) FNR
                        lookfor = follows[$i]
                }
}

END {
        for (i in record)
                printf "%s:\t%s\n", i, record[i]
}

Ejecutando esto en sus datos de ejemplo:

$ awk -f script.awk file
foo:    1 12 15
bar:    5 15 21

El script configura una followslista asociativa. La lista dice que cuando se encuentra foo, debemos buscar bar, y cuando se encuentra bar, nos interesa encontrar foonuevamente.

El script awkbusca las cadenas en lookfor. Inicialmente, busca cualquiera de las claves en la matriz followsy luego usa esta matriz para establecer lookforen la cadena que buscará a continuación. Cada vez que encuentra una cadena que está buscando, almacena el número de línea actual en la matriz asociativa recordpara la cadena correspondiente.

Al final, se emiten los números de línea recopilados en record.

La línea de aspecto funky -

record[$i] = (record[$i] == "" ? "" : record[$i] OFS ) FNR

agrega el número de línea al final de la cadena de números de línea en la matriz record. Si la cadena está vacía, simplemente la establece en el número de línea actual, pero si ya contiene algo, se inserta una coma entre la cadena existente y el número de línea.

0
28.01.2020, 00:38

EDIT :agregando una mejora para que coincida con su EDIT...

una sugerencia con awk:

BEGIN {
  ffoo=0; ffoos=""; fbars="";
} 
/foo/ {
  ffoo=1; ffoos=ffoos" "NR;
} 
/bar/ {
  if ((match($0, "foo") == 0) && (ffoo!=0)) {
    fbars=fbars" "NR; 
    ffoo=0;
  }
} 
END {
  print "linenumbersfoo: "ffoos"\n"; 
  print "linenumbersbar: "fbars"\n";
}
0
28.01.2020, 00:38
for i in `awk '/foo/{print NR}' filename`; do sed -n "$i,/bar/{;=;p}" filename|sed "N;s/\n/ /g"| awk '/foo|bar/'; done|awk '/bar/{print $1}'|perl -pne "s/\n/ /g"| awk '{print "linenumbersfoo: "$0}'

выход

linenumbersfoo: 1 12 


for i in `awk '/foo/{print NR}' filename`; do sed -n "$i,/bar/{;=;p}" o1|sed "N;s/\n/ /g"| awk '/foo|bar/'; done|awk '/bar/{print $1}'|perl -pne "s/\n/ /g"| awk '{print "linenumbersfoo: "$0}'

выход

linenumbersbar: 5 18 
-2
12.06.2021, 12:16

Теги

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