Intereting Posts
Может ли музыкальный плеер Clementine извлекать данные CDDB / FreeDB? Есть ли способ переименовать все файлы в каталоге? Curl зависает при загрузке с ftp Удаленный Unzip через SSH не работает оценивать несколько шаблонов из вывода программы и записывать в определенные шаблоны файлы Почему мой скрипт вызывает несколько функций? Ctrl-стрелка не работает в urxvt при использовании расширения с вкладками Bash – синтаксис в эхом Значения массива Bash, такие как переменные внутри цикла Может ли он разрешить только дерганный контент отправляться в буфер обмена, а между тем удаленный контент не работает? Как перенаправить stderr на переменную внутри if condition? удар Возможно ли монтировать две разные внешние файловые системы nfs в 2 каталога с одинаковым основанием (перекрытием)? Как удалить пунктирное подчеркивание из гиперссылок в Gnome Terminal Как завершить графический интерфейс в SunOS из shell-script Как uniq не является уникальным, что существует также uniq -unique?

Добавление содержимого содержимого в массив

В настоящее время у меня есть сценарий, который генерирует команды R на основе вывода find

#!/bin/bash PATHX="/path/to/my/files" find "${PATHX}" -maxdepth 1 -type f -name "*.csv" | while read d; do FN=$(echo -n "${d}" | cut -d/ -f5 | cut -d. -f1) echo "${FN}<-read.csv(\"${PATHX}/${FN}.csv\",header=TRUE)" # <snip> etc .etc. etc. echo "${FN}_2y<-tail(${FN}_log,730)" done 

Это отлично работает. Но у меня есть одна проблема с одной командой R:

 df<-data.frame(list,of,columns,goes,here) 

Я не могу понять, как я могу интегрировать это в find / while выше, а именно мне нужно вывести список $ {FN} _2y в функцию data.frame ().

Так, например, предположим, что мой скрипт выведен:

  • a_2y
  • b_2y
  • c_2y

Мне нужно получить df <-data.frame (a_2y, b_2y, c_2y)

Уточнение в дальнейшем для комментариев в комментариях, мне нужен только один экземпляр data.frame, прямо в самом конце, когда все входы csv были проанализированы.

Это проще делать в awk или perl чем в сценарии оболочки (хотя, если вы используете sh bash, which поддерживает массивы, это немного проще, чем при использовании sh без массивов. У вас все еще гораздо больше осложнений с цитированием и globbing или расширением, где вы не хотите его в сценарии оболочки, чем в perl или awk )

Например:

 #!/usr/bin/perl use strict; my $pathx='/path/to/my/files'; my $dh; my @frames=(); # get list of .csv files from $pathx opendir($dh, $pathx) || die "can't open directory '$pathx': $!\n"; my @csvfiles = grep { /\.csv$/ && -f "$pathx/$_" } readdir($dh); closedir($dh); foreach my $f (@csvfiles) { my @fields=split(/\./,$f); my $fn=$fields[@fields-2]; # perl array indices start from 0, not 1. printf '%s<-read.csv("%s",header=TRUE)'."\n", $fn, "$pathx/$f"; # <snip> etc .etc. etc. printf '%s_2y<-tail(%s_log,730)'."\n", $fn, $fn; push @frames,"${fn}_2y"; } print "df-<data.frame(", join(',',@frames), ")\n"; 

ПРИМЕЧАНИЕ. Вы можете использовать модуль File::Find вместо простого readdir() если вам нужна рекурсия каталога.

Пример вывода (с файлами a.csv , b.csv и c.csv ):

 a<-read.csv("/path/to/my/files/a.csv",header=TRUE) a_2y<-tail(a_log,730) b<-read.csv("/path/to/my/files/b.csv",header=TRUE) b_2y<-tail(b_log,730) c<-read.csv("/path/to/my/files/c.csv",header=TRUE) c_2y<-tail(c_log,730) df-<data.frame(a_2y,b_2y,c_2y) 

или с awk :

ПРИМЕЧАНИЕ. У awk нет функции join() поэтому мне пришлось написать ее. awk также не имеет функции readdir() , поэтому проще всего просто readdir() вывод find к нему (напишите сценарий оболочки для этого, если это необходимо).

 #!/usr/bin/awk -f BEGIN { FS="[./]"; delete A; # has side-effect of defining A as an array }; # i isn't an argument to this function, it's a local variable. # in awk, extra whitespace separates function args from declaration # of local variable(s) function join(array,sep, i) { result=array[1]; # awk array indices start from 1 for (i=2;i<=length(array);i++) result = result sep array[i]; return result; }; # main code block, run on every input line { fn=$(NF-1); printf "%s<-read.csv(\"%s\",header=TRUE)\n", fn, $0; # <snip> etc .etc. etc. printf "%s_2y<-tail(%s_log,730)\n", fn, fn; A[length(A)+1] = sprintf("%s_2y",fn); }; END { print "df-<data.frame(" join(",",A) ")"; } 

сохранить как, например, myscript.awk , сделать его исполняемым с помощью chmod и запустить как:

 find "${PATHX}" -maxdepth 1 -type f -name "*.csv" | ./myscript.awk 

Вывод идентичен версии perl .

Наконец, тот же алгоритм в bash:

 #!/bin/bash PATHX="/path/to/my/files" declare -a frames=() # get list of .csv files and store in array csvfiles. csvfiles=( $(find "$PATHX" -maxdepth 1 -type f -name '*.csv' ) ) function join() { local sep result i sep="$1" ; shift result="$1" ; shift for i in "$@" ; do result="$result$sep$i" ; done printf '%s' "$result" } for f in "${csvfiles[@]}" ; do fn=$(basename "$f" '.csv') printf "%s<-read.csv(\"%s\",header=TRUE)\n" $fn $f; # <snip> etc .etc. etc. printf "%s_2y<-tail(%s_log,730)\n" $fn $fn; frames+=( "${fn}_2y" ) done echo 'df-<data.frame('$( join ',' "${frames[@]}" )')'; 

Это позволяет избежать цикла while read while, который почти всегда является самым худшим способом обработки ряда строк в сценарии оболочки. Используйте awk или perl или sed или цикл for вокруг массива – все, чтобы избежать использования цикла while while.

Вы можете собрать имена в переменной fns и повторить это в конце. Поскольку у вас есть труба, вам нужно сохранить переменную в той же подоболочке, что и while / do / done. ${fns:1} является подстрокой переменной, отбрасывая начальную дополнительную запятую.

 #!/bin/bash PATHX="/path/to/my/files" find "${PATHX}" -maxdepth 1 -type f -name "*.csv" | ( fns= while read d; do FN=$(echo -n "${d}" | cut -d/ -f3 | cut -d. -f1) echo "${FN}<-read.csv(\"${PATHX}/${FN}.csv\",header=TRUE)" # <snip> etc .etc. etc. echo "${FN}_2y<-tail(${FN}_log,730)" fns+=",${FN}_2y" done echo "df<-data.frame(${fns:1})" )