Как удалить путь из входной переменной FILENAME в awk - доступно ли базовое имя каким-либо образом? - PullRequest
3 голосов
/ 13 марта 2019

Следующая команда

gawk '{print $0, FILENAME}' input.txt > result.txt

где input.txt:

FIXED3 LENGTH7      FILE FORMAT     00001
FIXED2 LENGTH8      FILE FORMAT     00002
FIXED2 LENGTH20     FILE FORMAT     00003
FIXED1 LENGTH20     FILE FORMAT     00004

Создает следующее Желаемое результат:

FIXED3 LENGTH7      FILE FORMAT     00001 input.txt
FIXED2 LENGTH8      FILE FORMAT     00002 input.txt
FIXED2 LENGTH20     FILE FORMAT     00003 input.txt
FIXED1 LENGTH20     FILE FORMAT     00004 input.txt

Однако, если использовать путь к файлу, как показано ниже:

gawk '{print $0, FILENAME}' /cygdrive/c/dev/data/input.txt > result.txt

Тогда FILENAME, добавляемый к каждой строке, также включает путь.Это то, что я хочу исправить. Я хотел бы получить тот же результат, что и в первом сценарии выше.

FIXED3 LENGTH7      FILE FORMAT     00001 /cygdrive/c/dev/data/input.txt
FIXED2 LENGTH8      FILE FORMAT     00002 /cygdrive/c/dev/data/input.txt
FIXED2 LENGTH20     FILE FORMAT     00003 /cygdrive/c/dev/data/input.txt
FIXED1 LENGTH20     FILE FORMAT     00004 /cygdrive/c/dev/data/input.txt

Ответы [ 5 ]

3 голосов
/ 13 марта 2019

Разделить FILENAME с / на массив и вывести последний элемент массива:

awk '{n=split(FILENAME,array,"/"); print $0, array[n]}' /cygdrive/c/dev/data/input.txt
3 голосов
/ 13 марта 2019

Это один из способов:

$ gawk '{f=FILENAME; sub(/^.*\//,"",f); print $0, f}' ../here/file
FIXED3 LENGTH7      FILE FORMAT     00001 file
FIXED2 LENGTH8      FILE FORMAT     00002 file
FIXED2 LENGTH20     FILE FORMAT     00003 file
FIXED1 LENGTH20     FILE FORMAT     00004 file

Объяснено:

$ gawk '{
    f=FILENAME          # copy the filename to f
    sub(/^.*\//,"",f)   # process f instead, removeall from beginning to last /
    print $0, f         # etc. etc.
}' ../here/file

или так как вы упомянули gawk:

$ gawk '{print $0, gensub(/^.*\//,"",1,FILENAME)}' ../here/file
1 голос
/ 14 марта 2019

Небольшая настройка для эффективности и краткости:

gawk 'FNR==1{f=gensub(".*/","",1,FILENAME)} $(NF+1)=f'

Извлекайте filename (f здесь) только один раз из каждого файла, выполняя эту часть в первой строке.
Ипоскольку FILENAME не будет пустым, поэтому просто добавьте его в строку, {print $0} будет подразумеваться.

Однако это изменит выходной разделитель, если он не будет одним пробелом.
Используйте знак ниже единицы, если это не то, что вы хотели:

gawk 'FNR==1{f=gensub(".*/","",1,FILENAME)}{print $0 OFS f}'
0 голосов
/ 14 марта 2019

Другой awk с использованием / в качестве разделителя

gawk -F"/"  ' { printf("%s ",$0) ; $0=FILENAME } { print $NF } ' /home/full/path/input.txt

с заданными вами входами

$ cat /cygdrive/c/dev/data/input.txt
FIXED3 LENGTH7      FILE FORMAT     00001
FIXED2 LENGTH8      FILE FORMAT     00002
FIXED2 LENGTH20     FILE FORMAT     00003
FIXED1 LENGTH20     FILE FORMAT     00004

$ gawk -F"/"  ' { printf("%s ",$0) ; $0=FILENAME } { print $NF } ' /cygdrive/c/dev/data/input.txt
FIXED3 LENGTH7      FILE FORMAT     00001 input.txt
FIXED2 LENGTH8      FILE FORMAT     00002 input.txt
FIXED2 LENGTH20     FILE FORMAT     00003 input.txt
FIXED1 LENGTH20     FILE FORMAT     00004 input.txt

$
0 голосов
/ 14 марта 2019

Не могли бы вы попробовать следующее. Он будет работать только в первой строке, чтобы получить точное имя файла Input_file, и НЕ будет запускаться в каждой строке файла.

awk 'FNR==1{if(FILENAME~/\//){sub(/.*\//,"",FILENAME)}} {print $0,FILENAME}' Input_file

Возможные преимущества этого подхода:

1 - НЕ генерировать отредактированное имя файла в каждой строке, получение происходит в самой 1-й строке и просто печатается во всех других строках.

2 - НЕТ массива / заполнителя памяти, созданного, так что это также должно быть БЫСТРОМ для файла большого размера.

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



РЕДАКТИРОВАТЬ: Просто еще одна мысль, вы можете просто перейти к новому каталогу, где присутствует Input_file и может вернуться в сам код / ​​один вкладыш, как пример, как показано ниже. ИМХО, я надеюсь, что это будет САМОЕ БЫСТРОЕ среди всех упомянутых здесь решений (так как мы НЕ делаем никаких манипуляций с данными здесь, и более того, мы используем ту же команду, которую вы использовали ранее :))

cd  /cygdrive/c/dev/data/ && awk '{print $0,FILENAME}' input.txt && cd -

Особенность этой команды будет в том, что она вернется в исходную директорию, в которой вы запускаете код, так что вы никогда не почувствуете, что перемещались куда-либо:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...