`sed`에서 문자열의 문자 사이에 하나의 "&"를 어떻게 넣을 수 있습니까?


11

sed다음과 같은 것을 만들 수 있습니다 :

12345

된다 :

1&2&3&4&5

?

답변:


25

GNU로 sed:

sed 's/./\&&/2g'

( substitute 각 ( g) 문자 ( .(동일한)와 &함께 선행) &( \&)하지만 만 초부터 발생을 ( 2)).

포터블 :

sed 's/./\&&/g;s/&//'

(모든 발생을 교체 &하고 원하지 않는 것을 제거하십시오 ).

일부 awk구현의 경우 (빈 FS에 대해 동작이 지정되지 않아 POSIX가 아님) :

awk -F '' -v OFS="&" '{$1=$1;print}'

( gawk몇 가지 다른 awk구현을 사용 하면 빈 필드 구분 기호는 레코드를 해당 문자 구성 요소로 분할합니다 . 출력 필드 구분 기호 ( OFS)는로 설정됩니다 &. 값을 $1(자체)에 할당 하여 새 필드 구분 기호로 레코드를 강제로 재생성합니다. 인쇄하기 전에 NF=NF작동하며 많은 awk 구현에서 약간 더 효율적이지만 그렇게 할 때의 동작은 현재 POSIX에서 지정되지 않습니다).

perl:

perl -F -lape '$_=join"&",@F' 

( -pe모든 줄에 대해 코드를 실행하고 결과 ( $_)를 인쇄하고, -l줄 끝을 자동으로 제거하고 다시 추가 합니다. 여기에 빈 문자열 인에 설정된 구분 기호에 입력 분할로 -a채워집니다 . 결과는 모든 문자를 , 그런 다음 '&'로 연결하고 줄을 인쇄하십시오.)@F-F@F

또는

perl -pe 's/(?<=.)./&$&/g' 

(다른 문자가 앞에 오는 모든 문자를 대체하십시오 (regexp 연산자 뒤에 보입니까 (? <= ...)).

zsh쉘 연산자 사용 :

in=12345
out=${(j:&:)${(s::)in}}

(다시, s::매개 변수 확장 플래그를 사용하여 빈 필드 구분 기호로 분할 하고와 결합 &)

또는:

out=${in///&} out=${out#?}

( 빈 패턴으로 다른 것을 의미 하지만 다른 것을 의미 하지는 않지만) ksh 연산자 를 &사용하여 모든 문자가 발생하기 전에 모든 문자를 대체 하고 POSIX 스트립으로 첫 번째 문자를 제거하십시오. 운영자).${var//pattern/replacement}kshbash${var#pattern}

ksh93쉘 연산자 사용 :

in=12345
out=${in//~(P:.(?=.))/\0&}

( ~(P:perl-like-RE)perl과 같은 정규 표현식을 사용하는 ksh93 glob 연산자 (perl 또는 PCRE와는 다름), (?=.)look-ahead 연산자 : 다른 문자가 뒤에 오는 문자 ( \0) 및 &)

또는:

out=${in//?/&\0}; out=${out#?}

(모든 캐릭터 ( ?)를 &그 자체로 교체하고 ( ) \0슈퍼 플로우 스를 제거합니다)

bash쉘 연산자 사용 :

shopt -s extglob
in=12345
out=${in//@()/&}; out=${out#?}

(같은 zsh당신이 필요로하는 것을 제외하고,의 @()가 (당신이 필요로하는 ksh에서의 글로브 운영자 extglobbash)).


2
@AFSHIN, 그것은 012345입력에서 작동하지 않을 것입니다
Stéphane Chazelas

1
이 작동합니다awk -F '' -v OFS="&" 'NF=NF'
αғsнιη

1
@AFSHIN이지만 빈 줄을 제거하십시오. 보다 일반적으로, 조치를 조건으로 사용하고 조치 결과를 인쇄하려는 경우 조치에 의해 리턴되는 값이 빈 문자열 또는 0으로 해석되는 숫자 문자열이 아닌지 확인해야합니다.
Stéphane Chazelas

1
이러한 각각의 작동 방식에 대한 간단한 설명을 추가 할 수 있습니까? 여기서 배울 점이 멋진 것처럼 보이지만,이 특정 문제의 범위 밖에서 적용하는 방법을 찾기 위해 대부분의 연구를 시작한 곳조차 알지 못합니다.
IMSoP

1
@ StéphaneChazelas Brilliant, 감사합니다. sed와 같은 것에 대한 복잡한 문서를 검색하는 것은 약간의 기술이므로 실제 예제를 사용하는 것은 이전에는 보지 못했던 새로운 비트를 배우는 좋은 방법입니다.
IMSoP

15

유닉스 유틸리티 :

fold -w1|paste -sd\& -

설명 :

"fold -w1" -각 입력 문자를 자체 줄로 줄 바꿈합니다.

접기-지정된 너비에 맞게 각 입력 줄을 줄 바꿈

-w, --width = WIDTH는 80 대신 WIDTH 열을 사용합니다.

%echo 12345|fold -w1
1
2
3
4
5

"paste -sd\& -"- &구분자로 사용하여 입력 행을 병합합니다.

붙여 넣기-파일 라인 병합

-s, --serial 대신 한 번에 한 파일 씩 붙여 넣기

-d, --delimiters = LIST는 TAB 대신 LIST의 문자를 재사용합니다.

%fold -w1|paste -sd\& -
1&2&3&4&5

(입력에 여러 줄이 포함되어 있으면이 줄과 결합됩니다. &)


2
멀티 바이트 문자가 실패합니다. 체험echo "abcdeéèfg" | fold -1 | paste -sd\& -
Isaac

3
@Arrow 대부분의 경우 유니 코드를 완전히 지원하지 않는 버그있는 coreutils 버전의 fold를 사용하고있을 것입니다 . BSD 접기, RedHat 패치 버전의 coreutils (예 : Fedora 또는 CentOS)와 BusyBox 구현은 유니 코드를 잘 처리 할 수 ​​있습니다.
zeppelin

5
질문은 구체적으로 sed입니다.
Alexander

6
@Alexander-사실이며, sed아래에 유용한 답변이 많이 있습니다. 그리고 다른 방법으로 과제를 어떻게 해결할 수 있는지 시연하는 데 아무런 해가 없습니다.
zeppelin

@ StéphaneChazelas> POSIXly, 당신은 fold -w 1이 필요합니다. 사실, 나는 "-w"thx를 추가했습니다 ! "-"차례대로되지 않는 요구 If no file operands are specified, the standard input shall be used
제플린


9
sed 's/\B/\&/g'

\ B- 단어 경계를 제외한 모든 곳에서 일치합니다. 즉, 왼쪽의 문자와 오른쪽의 문자가 모두 "단어"문자이거나 "단어 이외"문자 인 경우 일치합니다.

정보 : GNU sed 매뉴얼, 정규 표현식 확장 .

테스트 :

sed 's/\B/\&/g' <<< '12345'
1&2&3&4&5

5
흥미로운 아이디어이지만 질문에는 문자열에 공백, 점 또는 단어 경계를 구성 할 수있는 것이 포함되어 있지 않다고 말하지 않습니다. "문자 사이"라고 표시되며 "모든 문자"로 해석되어야합니다.
xhienne

4

이것은 다른 답변보다 약간 느리지 만 매우 분명합니다.

echo 12345 | perl -lnE 'say join "&", split //'

4

다른 방법이 있습니다. sed 표현식의 첫 번째 부분은 모든 문자를 캡처 한 다음 문자 및 앰퍼샌드로 바꿉니다. 두 번째 부분은 라인의 끝에서 앰퍼샌드를 제거합니다.

echo 12345 | sed -r 's/(.)/\1\&/g;s/\&$//g'
1&2&3&4&5

멀티 바이트 문자에서도 작동합니다.


1
스크립트를 sed두 번 호출 할 필요가 없습니다 . sed스크립트에 여러 명령이있을 수 있습니다.sed -r 's/(.)/\1\&/g; s/\&$//g'
xhienne

xhienne, 고마워, TIL! 답변을 업데이트했습니다.
Alexander
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.