따옴표로 묶인 항목이있는 쉼표로 구분 된 목록으로 별도의 줄 바꾸기


15

다음 데이터 (Rmarkdown 파일에서 구문 분석 된 R 패키지 목록)가 있는데 R로 전달하여 설치할 수있는 목록으로 바꾸고 싶습니다.

d3heatmap
data.table
ggplot2
htmltools
htmlwidgets
metricsgraphics
networkD3
plotly
reshape2
scales
stringr

목록을 양식 목록으로 바꾸고 싶습니다.

'd3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scales', 'stringr'

현재 원시 파일에서 위의 목록으로 이동하는 bash 파이프 라인이 있습니다.

grep 'library(' Presentation.Rmd \
| grep -v '#' \
| cut -f2 -d\( \
| tr -d ')'  \
| sort | uniq

새 줄을 쉼표로 구분 된 목록으로 바꾸는 단계를 추가하고 싶습니다. 추가를 시도했지만 tr '\n' '","'실패합니다. 또한 다음과 같은 여러 가지 스택 오버플로 답변을 시도했지만 실패했습니다.

결과적으로 생성 library(stringr)))phics)됩니다.

결과적으로 생성 ,%됩니다.

이 응답 ( -i플래그가 제거 된 상태)은 입력과 동일한 출력을 생성합니다.


구분 기호는 쉼표 공백이어야합니까, 아니면 쉼표 만 허용됩니까?
steeldriver

어느 괜찮지 만, 나는 문자열을 둘러싼 인용 문자가 필요하거나 않습니다 '또는 ".
fbt


입력 데이터와이를 처리하는 스크립트가 완전히 호환되지 않음을 가장 먼저 알 수 있습니다. 출력이 없습니다.
ctrl-alt-delor

내가 나열한 스크립트는 입력 데이터를 생성하는 방법입니다. 누군가가 그것을 요구했다. 실제 입력 데이터는 다음과 같습니다 . Github은 새로운 라인을 제거하기 위해 형식을 변경합니다.
fbt

답변:


19

sed로 따옴표를 추가 한 후 다음 과 같이 paste 를 사용하여 행을 병합하십시오 .

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

GNU coreutils 기반 시스템 (예 : Linux)을 실행중인 경우 후행을 생략 할 수 있습니다 '-'.

입력 데이터에 DOS 스타일 줄 끝이 있으면 (@phk에서 제안한대로) 다음과 같이 명령을 수정할 수 있습니다.

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

1
MacOS (및 기타)에서는 입력이 파일이 아닌 stdin에서 온 것을 나타 내기 위해 대시를 포함해야합니다.sed 's/^\|$/"/g'|paste -sd, -
cherdt

사실 "coreutils"버전의 페이스트는 두 형식을 모두 사용할 수 있지만 "-"는 POSIX가 더 많습니다. 고마워 !
zeppelin

2
또는 sed혼자 :sed 's/.*/"&"/;:l;N;s/\n\(.*\)$/, "\1"/;tl'
Digital Trauma

1
@fbt 이제 답변 끝에 추가 한 메모가 여기에도 적용됩니다.
phk

1
@DigitalTrauma-정말 좋은 생각은 아닙니다. 그것은 매우 느릴 것입니다 (거대한 파일로 중단 될 수도 있음) .Q에 대한 내 의견에 링크 된 QI에 대한 답변을 참조하십시오. 멋진 것은 paste혼자 사용하는 것입니다 ;)
don_crissti

8
사용 awk:
awk 'BEGIN { ORS="" } { print p"'"'"'"$0"'"'"'"; p=", " } END { print "\n" }' /path/to/list
쉘 이스케이프가 적고 더 읽기 쉬운 대안 :
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 { print "\n" }. 첫 번째 항목을 인쇄 한 후 변수 p가 설정됩니다 (빈 문자열과 같기 전에). 이 변수를 사용하면 p모든 항목 (또는 awk-speak : record ) 앞에 접두사가 추가되고 작은 따옴표가 추가로 인쇄됩니다. awk출력 레코드 분리 변수 ORS가 상기 빈으로 설정되도록 (접두사 당신을 위해 그 일을하기 때문에) 필요하지 않습니다 BEGINING. 아 그리고 우리 END는 줄 바꿈으로 파일을 만들 수 있습니다 (예 : 추가 텍스트 처리 도구와 함께 작동합니다). 이것이 필요하지 않은 부분 END과 그 이후의 모든 부분 (작은 따옴표)을 제거 할 수 있습니다.

노트

Windows / DOS 스타일 줄 끝 ( \r\n)이 있으면 \n먼저 UNIX 스타일 ( ) 로 변환해야합니다 . 이렇게하려면 tr -d '\015'파이프 라인의 시작 부분에 넣을 수 있습니다 .

tr -d '\015' < /path/to/input.list | awk […] > /path/to/output

( \r파일에서 s를 사용하지 않는다고 가정합니다. 여기에서 매우 안전한 가정입니다.)

또는 dos2unix /path/to/input.list한 번만 실행 하면 파일을 전체 위치로 변환 할 수 있습니다.


이 명령을 실행 ', 'stringr23aphics하면 출력으로 나타납니다.
fbt

@fbt 내 최신 메모를 참조하십시오.
phk

2
print p"'"'"'"$0"'"'"'"; p=", "— 거룩한 인용문, 배트맨!
wchargin

나는 알고 있습니다.‽ :) 많은 쉘에서 인쇄 p"'\''"$0"'\''";가 효과가 있었지만 (POSIXy는 아니지만) 또는 bashC 인용 문자열 ( $'')을 사용하더라도 print p"\'"$0"\'";(다른 백 슬래시를 두 배로 늘릴 필요가 있음) 언급했지만 이미 awk문자 이스케이프를 사용하는 다른 방법 입니다.
phk

와우, 난 당신이 알아 낸 것을 믿을 수 없어. 감사합니다.
fbt

6

@don_crissti의 링크 된 답변에서 알 수 있듯이 붙여 넣기 옵션은 엄청나게 빠릅니다. 리눅스 커널의 파이핑은 지금 막 시도하지 않았다면 내가 생각했던 것보다 훨씬 효율적입니다. 놀랍게도, 쉼표 + 공백이 아닌 목록 항목을 구분하는 단일 쉼표, 페이스트 파이프 라인에 만족할 수 있다면

(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/.*/'&'/, slurp과 a 가 이어집니다 s/\n/, /g.


편집 : 터무니없는 경계, 빈 공간을 능가하기 위해 플렉스를 얻는 것은 상당히 쉽습니다. 내장 멀티 스레드 / 신호 처리기 동기화가 필요하지 않은 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 배 이상 빠릅니다.


1
(paste -d\ \'\' /dev/null /dev/null - /dev/null | paste -sd, -) <infile | cut -c2-비록 당신이 언급 한 것처럼 거의 같은 속도로 쉼표 + 공간을 할 것입니다. 구분자로 멋진 문자열이 필요하다면 정말 유연하지 않습니다
don_crissti

flex물건은 꽤 망할 멋진 사람입니다 ...이 사람 flex이이 사이트에 코드를 게시하는 것을 처음으로 보게 됩니다 ... 큰 공감대! 이 내용을 더 게시하십시오.
don_crissti

@don_crissti 감사합니다! 나는 좋은 기회를 찾고, sed / awk / whatnot는 일반적으로 편의 가치를위한 더 나은 옵션이지만 종종 매우 쉬운 플렉스 답변도 있습니다.
jthill

4

파이썬 원 라이너 :

$ 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', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scales', 'stringr'


IIRC, 파이썬 join은 반복자를 사용할 수 있어야하므로 stdin 루프를 목록에 구체화 할 필요가 없습니다
iruvar

@iruvar 예, OP의 원하는 출력을 제외하고 각 단어를 인용하고 출력을 한 줄로 유지하려면 후행 줄 바꿈을 제거해야합니다. 당신은 목록 이해없이 그것을하는 방법을 알고 있습니까?
Sergiy Kolodyazhnyy

3

데이터가 파일 텍스트에 있다고 가정하면 다음이 제대로 수행되어야한다고 생각합니다.

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'

나는 이것이 당신이 찾고있는 것이라고 믿습니까?


1
좋은 해결책. 그러나 OP는 명시 적으로 요청하지 않았으며 bash누군가가 그것을 사용할 수 있다고 가정하는 것이 안전하지만 (모든 AFAIK는 가장 많이 사용되는 쉘임) 여전히 당연한 것으로 간주해서는 안됩니다. 또한 인용에서 더 나은 일을 할 수있는 부분이 있습니다 (큰 따옴표로 묶음). 예를 들어, 패키지 이름에 공백이 없을 것 같지만 변수를 인용하지 않고 인용하는 것이 좋습니다. shellcheck.net 을 실행 하여 메모와 설명을 참조하십시오.
phk

2

종종 비슷한 시나리오가 있습니다. Excel에서 열을 복사하고 쉼표로 구분 된 목록으로 변환하고 싶습니다 (나중에 SQL 쿼리에서 사용하기 위해 ... WHERE col_name IN <comma-separated-list-here>).

이것이 내 .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 줄에서 ( "line by line") 을 실행 하고 클립 보드의 내용을 붙여 넣은 다음 키를 누르면 <C-D>함수는로 둘러싸인 입력을 반환합니다 (). 이것은 다음과 같습니다 :

$ lbl
1
2
3
dos2unix: converting file /tmp/tmp.OGM6UahLTE to Unix format ...
(1,2,3)

(dos2unix를 왜 여기에 넣었는지 기억이 나지 않을 것입니다. 회사 설정에 문제가 자주 있기 때문입니다.)


1

sed의 일부 버전은 약간 다르게 작동하지만 내 Mac에서는 sed에서 "uniq"를 제외한 모든 것을 처리 할 수 ​​있습니다.

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 '...'

-폴


2
Unix.stackexchange에 오신 것을 환영합니다! 나는 당신 이 여행을하는 것이 좋습니다 .
Stephen Rauch

0

R 패키지의 일반 텍스트 목록을 사용하여 R에 설치하면 R에서 직접 해당 목록을 사용하는 솔루션을 제안하지 않았지만 bash, perl, python, awk, sed 또는 따옴표와 쉼표를 넣는 모든 항목과 싸우십시오. 명부. 이것은 전혀 필요하지 않으며 R의 변환 된 목록을 입력하고 사용하는 방법을 해결하지 못합니다.

일반 텍스트 파일 ( packages.txtSaid , )을 단일 변수가있는 데이터 프레임으로 로드하면으로 직접 사용할 수있는 벡터로 추출 할 수 있습니다 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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.