Преобразование отдельных строк в список, разделенный запятыми, с записями в кавычках

Хорошо, я решил эту проблему. DSM Synology чувствителен к регистру имен пользователей.

15
23.05.2017, 15:40
8 ответов
Использование 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 один раз, чтобы преобразовать файл на месте.

11
27.01.2020, 19:49

Вы можете добавить кавычки с помощью sed , а затем объединить строки с помощью paste , например:

sed 's/^\|$/"/g'|paste -sd, -

Если вы используете систему на основе GNU coreutils (например, Linux), вы можете опустить завершающий '-' .

Если вы вводите данные с окончанием строки в стиле DOS (как предлагается @phk), вы можете изменить команду следующим образом:

sed 's/\r//;s/^\|$/"/g'|paste -sd, -
28
27.01.2020, 19:49

Perl

Однострочник 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

Perl

По сути та же идея, что и раньше: прочитать все строки, удалить завершающую новую строку, заключить в одинарные кавычки, поместить все в массив @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 '

4
27.01.2020, 19:49

Некоторые версии 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

1
27.01.2020, 19:49

Я думаю, что следующее должно работать нормально, при условии, что ваши данные находятся в файле 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'

Я думаю, это было то, что вы искали?

4
27.01.2020, 19:49

Как показывает связанный ответ @ 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 раз быстрее, чем все остальное.

7
27.01.2020, 19:49

У меня часто бывает очень похожий сценарий: я копирую столбец из 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, предположительно потому, что это часто вызывает проблемы в настройке моей компании.)

2
27.01.2020, 19:49

Забавно, что для использования простого текстового списка пакетов 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)
1
27.01.2020, 19:49

Теги

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