여러 줄 문자열을 쉼표로 구분 된 단일 문자열로 바꾸기


95

다음 문자열이 있다고 가정 해 보겠습니다.

something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)

어떻게 간단히

+12.0,+15.5,+9.0,+13.5

bash에서?


잠시 뒤로 물러서서이 스레드를 프로그래밍 언어로서의 bash에 대한 눈부신 기소라고 생각합시다. Scala listOfStuff mkString ", "또는 Haskell을 고려하십시오intercalate ", " listOfString
FP Freely

답변:


92

awksed다음을 사용할 수 있습니다 .

awk -vORS=, '{ print $2 }' file.txt | sed 's/,$/\n/'

또는 파이프를 사용하려는 경우 :

echo "data" | awk -vORS=, '{ print $2 }' | sed 's/,$/\n/'

분석하려면 :

  • awk 필드로 분류 된 데이터를 처리하는 데 탁월합니다.
  • -vORS=,"출력 레코드 구분 기호"를 ,원하는대로 설정합니다.
  • { print $2 }awk모든 레코드 (라인)에 대해 두 번째 필드를 인쇄하도록 지시 합니다.
  • file.txt 당신의 파일 이름입니다
  • sed후행을 제거 ,하고 개행으로 바꿉니다 (개행을 원하지 않으면 할 수 있습니다 s/,$//)

1
awk : 잘못된 -v 옵션 :(
Marsellus Wallace

6
-v와 ORS = 사이에 공백 추가, (저는 osx에서)
Graham P Heath

파이프 분리를 위해 동일한 명령을 수행하는 방법은 무엇입니까? awk -v ORS=| '{ print $1 }' DCMC.rtf | sed 's/,$/\n/'오류가 발생합니다
Yogesh

2
이상하게도 이렇게하려고하면 출력이 비어 있습니다.
eternaltyro

1
파이프 된 버전의 경우 {print $1}그렇지 않으면 쉼표 만 출력됩니다
Przemysław Czechowski

162

깨끗하고 간단합니다.

awk '{print $2}' file.txt | paste -s -d, -

3
이 여기에 가장 좋은 대답, 그리고 분명이 할 수있는 올바른 방법입니다
forresthopkinsa

작은 따옴표 / 큰 따옴표로 모든 값을 어떻게 인용합니까?
Hussain

1
@Hussaincat thing | awk -F',' '{ print "'\''" $7 "'\' '" }' | paste -s -d ','
starbeamrainbowlabs

,'구분자로 어떻게 사용 합니까?
Kasun Siyambalapitiya

문자열에 CRLF가있는 경우 Windows 개행 (예 : 사용 dos2unix) 을 처리해야 합니다.
Bowi


10
$ awk -v ORS=, '{print $2}' data.txt | sed 's/,$//'
+12.0,+15.5,+9.0,+13.5

$ cat data.txt | tr -s ' ' | cut -d ' ' -f 2 | tr '\n' ',' | sed 's/,$//'
+12.0,+15.5,+9.0,+13.5

AWK의 입력은 표준 입력을 통해서였다 경우에 대해 (단지 무엇을 넣어 환호, function | awk...당신의 예에?
알렉스 코플란



8

이것은 당신을 위해 일할 수 있습니다.

cut -d' ' -f5 file | paste -d',' -s
+12.0,+15.5,+9.0,+13.5

또는

sed '/^.*\(+[^ ]*\).*/{s//\1/;H};${x;s/\n/,/g;s/.//p};d' file
+12.0,+15.5,+9.0,+13.5

또는

sed 's/\S\+\s\+//;s/\s.*//;H;$!d;x;s/.//;s/\n/,/g' file

파일의 각 행에 대해; 첫 번째 필드와 다음 공백을 잘라 내고 두 번째 필드 다음의 나머지 줄을 잘라 내고 보류 공간에 추가합니다. 홀드 공간으로 교체 한 마지막 줄을 제외한 모든 줄을 삭제하고 처음에 도입 된 줄 바꿈을 삭제 한 후 모든 줄 바꿈을 ,'s 로 변환합니다 .

NB 작성 가능 :

sed 's/\S\+\s\+//;s/\s.*//;1h;1!H;$!d;x;s/\n/,/g' file

4

다음을 사용할 수 있습니다 grep.

grep -o "+\S\+" in.txt | tr '\n' ','

로 시작하는 문자열이 발견되는 +문자열 다음을, \S\+다음, 쉼표로 새로운 라인 문자를 변환합니다. 대용량 파일의 경우 매우 빠릅니다.


4

이 쉬운 코드를 시도하십시오.

awk '{printf("%s,",$2)}' File1

3

이 시도:

sedSelectNumbers='s".* \(+[0-9]*[.][0-9]*\) .*"\1,"'
sedClearLastComma='s"\(.*\),$"\1"'
cat file.txt |sed "$sedSelectNumbers" |tr -d "\n" |sed "$sedClearLastComma"

좋은 점은 개행 "\ n"문자를 삭제하는 쉬운 부분입니다!

편집 : sed를 사용하여 한 줄에 줄을 연결하는 또 다른 좋은 방법은 다음과 같습니다. |sed ':a;N;$!ba;s/\n/ /g'got from here .


그 편집은 굉장합니다-+1!
JoeG 2013-08-30

2

순수 Bash로 작성된 솔루션 :

#!/bin/bash

sometext="something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)"

a=()
while read -r a1 a2 a3; do
    # we can add some code here to check valid values or modify them
    a+=("${a2}")
done <<< "${sometext}"
# between parenthesis to modify IFS for the current statement only
(IFS=',' ; printf '%s: %s\n' "Result" "${a[*]}")

결과 : + 12.0, + 15.5, + 9.0, + 13.5


2

awk로이 간단한 솔루션을 보지 못함

awk 'b{b=b","}{b=b$2}END{print b}' infile

0

Perl 사용 :

fg@erwin ~ $ perl -ne 'push @l, (split(/\s+/))[1]; END { print join(",", @l) . "\n" }' <<EOF
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)
EOF

+12.0,+15.5,+9.0,+13.5

0

두 개의 sed 호출로 수행 할 수도 있습니다.

$ cat file.txt 
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)
$ sed 's/^[^:]*: *\([+0-9.]\+\) .*/\1/' file.txt | sed -e :a -e '$!N; s/\n/,/; ta'
+12.0,+15.5,+9.0,+13.5

첫 번째 sed 호출은 관심없는 데이터를 제거하고 두 번째 호출은 모든 회선을 결합합니다.


0

다음과 같이 인쇄 할 수도 있습니다.

그냥 awk : printf 사용

bash-3.2$ cat sample.log
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)

bash-3.2$ awk ' { if($2 != "") { if(NR==1) { printf $2 } else { printf "," $2 } } }' sample.log
+12.0,+15.5,+9.0,+13.5

0

Dan Fego의 awk와 유사한 또 다른 Perl 솔루션 :

perl -ane 'print "$F[1],"' file.txt | sed 's/,$/\n/'

-a perl에게 입력 줄을 0부터 시작하는 @F 배열로 분할하도록 지시합니다.


0

가장 어려운 부분은 아마도 두 번째 "열"을 선택하는 것입니다. 여러 공백을 하나로 처리하는 쉬운 방법을 모르기 때문입니다. 나머지는 쉽습니다. bash 대체를 사용하십시오.

# cat bla.txt
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)

# cat bla.sh
OLDIFS=$IFS
IFS=$'\n'
for i in $(cat bla.txt); do
  i=$(echo "$i" | awk '{print $2}')
  u="${u:+$u, }$i"
done
IFS=$OLDIFS
echo "$u"

# bash ./bla.sh
+12.0, +15.5, +9.0, +13.5
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.