Хорошо, я решил эту проблему. DSM Synology чувствителен к регистру имен пользователей.
awk
:
awk 'BEGIN { ORS="" } { print p"'"'"'"$0"'"'"'"; p=", " } END { print "\n" }' /path/to/list
{{ 1}} Альтернатива с меньшим экранированием оболочки и, следовательно, более читабельной:
awk 'BEGIN { ORS="" } { print p"\047"$0"\047"; p=", " } END { print "\n" }' /path/to/list
Вывод:
'd3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scales', 'stringr'
Объяснение:
Сам скрипт awk
без всяких экранирований имеет вид BEGIN {ORS = "" } {print p "'" $ 0 "'"; p = ","} END {печать "\ n"}
. После печати первой записи устанавливается переменная p
(до этого она была как пустая строка). С помощью этой переменной p
каждая запись (или в awk
-speak: record ) имеет префикс и дополнительно печатается в одинарных кавычках. Переменная разделителя выходных записей awk
ORS
не нужна (поскольку префикс делает это за вас), поэтому она устанавливается пустой в BEGIN
ing. Да, и мы могли бы добавить в наш файл END
новую строку (например, чтобы он работал с другими инструментами обработки текста); если в этом нет необходимости, можно удалить часть с END
и все, что после нее (в одинарных кавычках).
Если у вас есть окончания строк в стиле Windows / DOS ( \ r \ n
), вы должны сначала преобразовать их в стиль UNIX ( \ n
).Для этого вы можете поместить tr -d '\ 015'
в начало вашего конвейера:
tr -d '\015' < /path/to/input.list | awk […] > /path/to/output
(Предполагая, что вы не используете \ r
в вашем Здесь очень безопасное предположение.)
В качестве альтернативы, просто запустите dos2unix /path/to/input.list
один раз, чтобы преобразовать файл на месте.
Вы можете добавить кавычки с помощью sed , а затем объединить строки с помощью paste , например:
sed 's/^\|$/"/g'|paste -sd, -
Если вы используете систему на основе GNU coreutils (например, Linux), вы можете опустить завершающий '-'
.
Если вы вводите данные с окончанием строки в стиле DOS (как предлагается @phk), вы можете изменить команду следующим образом:
sed 's/\r//;s/^\|$/"/g'|paste -sd, -
Однострочник Python:
$ python -c "import sys; print ','.join([repr(l.strip()) for l in sys.stdin])" < input.txt
'd3heatmap','data.table','ggplot2','htmltools','htmlwidgets','metricsgraphics','networkD3','plotly','reshape2','scales','stringr'
Работает очень просто - мы перенаправляем input.txt в stdin, используя <
], считайте каждую строку в список с помощью .strip ()
, удаляющего символы новой строки
, и repr ()
, создавая цитируемое представление каждой строки. Затем список объединяется в одну большую строку с помощью функции .join ()
с ,
в качестве разделителя
В качестве альтернативы мы могли бы использовать +
для объединения кавычек в каждая зачищенная линия.
python -c "import sys;sq='\'';print ','.join([sq+l.strip()+sq for l in sys.stdin])" < input.txt
По сути та же идея, что и раньше: прочитать все строки, удалить завершающую новую строку, заключить в одинарные кавычки, поместить все в массив @cvs и распечатать значения массива, соединенные запятыми.
$ perl -ne 'chomp; $sq = "\047" ; push @cvs,"$sq$_$sq";END{ print join(",",@cvs) }' input.txt
'd3heatmap', 'данные.table ',' ggplot2 ',' htmltools ',' htmlwidgets ',' metricsgraphics ',' networkD3 ',' plotly ',' reshape2 ',' scale ',' stringr '
Некоторые версии sed действуют немного иначе, но на моем Mac я могу обрабатывать все, кроме uniq в sed:
sed -n -e '
# Skip commented library lines
/#/b
# Handle library lines
/library(/{
# Replace line with just quoted filename and comma
# Extra quoting is due to command-line use of a quote
s/library(\([^)]*\))/'\''\1'\'', /
# Exchange with hold, append new entry, remove the new-line
x; G; s/\n//
${
# If last line, remove trailing comma, print, quit
s/, $//; p; b
}
# Save into hold
x
}
${
# Last line not library
# Exchange with hold, remove trailing comma, print
x; s/, $//; p
}
'
К сожалению, исправить уникальная часть, которую вы должны сделать примерно так:
grep library Presentation.md | sort -u | sed -n -e '...'
- Paul
Я думаю, что следующее должно работать нормально, при условии, что ваши данные находятся в файле text
d3heatmap
data.table
ggplot2
htmltools
htmlwidgets
metricsgraphics
networkD3
plotly
reshape2
scales
stringr
Давайте использовать массивы, в которых подстановка отключена:
#!/bin/bash
input=( $(cat text) )
output=( $(
for i in ${input[@]}
do
echo -ne "'$i',"
done
) )
output=${output:0:-1}
echo ${output//,/, }
Результат скрипта должен быть следующим:
'd3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scales', 'stringr'
Я думаю, это было то, что вы искали?
Как показывает связанный ответ @ don_crissti , опция вставки граничит с невероятной скоростью - конвейер ядра Linux более эффективен, чем я мог бы подумать, если бы я только что не попробовал его. Примечательно, что если вам нравится одна запятая, разделяющая элементы списка, а не запятая + пробел, конвейер вставки
(paste -d\' /dev/null - /dev/null | paste -sd, -) <input
работает быстрее, чем даже разумная программа flex
(!)
%option 8bit main fast
%%
.* { printf("'%s'",yytext); }
\n/(.|\n) { printf(", "); }
Но если просто приличная производительность приемлема (и если вы не проводите стресс-тест, вы не сможете измерить какие-либо различия с постоянным коэффициентом, все они мгновенные), и вам нужна как гибкость с вашими разделителями, так и разумная однострочность -y-ness,
sed "s/.*/'&'/;H;1h;"'$!d;x;s/\n/, /g'
- твой билет. Да, это похоже на линейный шум, но идиома H; 1h; $! D; x
- это правильный способ все пропустить, как только вы поймете, что все это действительно легко читается, это s /.*/'&'/
, за которым следует чавканье и s / \ n /, / g
.
edit: граничащее с абсурдом, довольно легко получить flex, чтобы превзойти все остальное, просто скажите stdio, что вам не нужна встроенная синхронизация многопоточности / обработчика сигналов:
%option 8bit main fast
%%
.+ { putchar_unlocked('\'');
fwrite_unlocked(yytext,yyleng,1,stdout);
putchar_unlocked('\''); }
\n/(.|\n) { fwrite_unlocked(", ",2,1,stdout); }
и при нагрузке это в 2-3 раза быстрее, чем вставьте конвейеры, которые сами по себе как минимум в 5 раз быстрее, чем все остальное.
У меня часто бывает очень похожий сценарий: я копирую столбец из Excel и хочу преобразовать содержимое в список, разделенный запятыми (для последующего использования в запросе SQL, например ... WHERE col_name IN
).
Это то, что у меня есть в моем .bashrc:
function lbl {
TMPFILE=$(mktemp)
cat $1 > $TMPFILE
dos2unix $TMPFILE
(echo "("; cat $TMPFILE; echo ")") | tr '\n' ',' | sed -e 's/(,/(/' -e 's/,)/)/' -e 's/),/)/'
rm $TMPFILE
}
Затем я запускаю lbl
(«строка за строкой») в строке cmd, которая ожидает ввода, вставляю содержимое из буфера обмена, нажимаю
, и функция возвращает ввод, окруженный ()
. Это выглядит так:
$ lbl
1
2
3
dos2unix: converting file /tmp/tmp.OGM6UahLTE to Unix format ...
(1,2,3)
(Я не помню, зачем я поместил здесь dos2unix, предположительно потому, что это часто вызывает проблемы в настройке моей компании.)
Забавно, что для использования простого текстового списка пакетов R для их установки в R никто не предложил решения, использующего этот список непосредственно в R, но бороться с bash, perl, python, awk, sed или чем-то еще, чтобы поставить кавычки и запятые в списке. Это вовсе не обязательно и, более того, не решает, как вводить и использовать преобразованный список в R.
Вы можете просто загрузить обычный текстовый файл (, как сказано,packages.txt
)как фрейм данных с одной переменной, которую вы можете извлечь как вектор, непосредственно используемый install.packages
. Итак, преобразовать его в пригодный для использования объект R и установить этот список просто:
df <- read.delim("packages.txt", header=F, strip.white=T, stringsAsFactors=F)
install.packages(df$V1)
Или без внешнего файла:
packages <-"
d3heatmap
data.table
ggplot2
htmltools
htmlwidgets
metricsgraphics
networkD3
plotly
reshape2
scales
stringr
"
df <- read.delim(textConnection(packages),
header=F, strip.white=T, stringsAsFactors=F)
install.packages(df$V1)