이 쿼리가 있습니다
sed '/./=' abc.txt| sed '/./N; s/\n/, /' >> as.dat
source file has 3 rows like below
a
b
c
다음 명령을 사용하면 다음과 같은 결과가 나타납니다.
Output
1 a
2 b
3 c
하지만 나는 다음과 같은 명령 출력을 원합니다.
Output
a 1
b 2
c 3
답변1
cut
유닉스에는 and 라고 불리는 멋진 작은 도구가 있습니다 paste
. 이 cut
도구는 열을 삽입하는 동안 입력에서 열 집합을 추출합니다 paste
. 우리는 이것을 사용할 것입니다.
나는 귀하의 파이프라인에 대해 별로 신경 쓰지 않고(지금은 이 답변의 끝 부분을 참조하십시오) 열 전환 문제에만 관심이 있습니다.
다음과 같은 파일에 데이터가 있다고 가정해 보겠습니다 cols.txt
.
$ cat cols.txt
1 a
2 b
3 c
$ paste -d ' ' cols.txt cols.txt
1 a 1 a
2 b 2 b
3 c 3 c
유틸리티는 paste
일반적으로 열 사이에 탭 문자를 삽입하지만 여기서는 공백( -d ' '
)을 삽입하도록 지시합니다.
paste
그런 다음 with 출력에서 두 번째와 세 번째 열을 추출합니다 cut
.
$ paste -d ' ' cols.txt cols.txt | cut -d ' ' -f 2,3
a 1
b 2
c 3
cut
우리 는 "필드 구분자"( , 그렇지 않으면 탭이 필요함)로 공백이 있고 필드 2와 3( ) -d ' '
을 갖고 싶다고 말했습니다 . -f 2,3
(아쉽게도 원래 입력의 cut
" " 열만 필요합니다.2,1
아니요열을 교환합니다. )
따라서 궁극적으로 여기서는 지저분한 정규식 마술이 필요하지 않습니다.
파이프라인으로 돌아가세요. 스크랩해봅시다. 각 행에 행 번호를 삽입하려는 것 같습니다. nl
("numberline") 이라는 또 다른 Unix 도구가 있습니다 .
$ nl abc.txt
1 a
2 b
3 c
기본적으로 비어 있지 않은 각 줄의 줄 번호를 가져옵니다. 앞에는 패딩을 위한 공백이 있고 탭으로 원래 줄과 구분됩니다. 빈 줄에도 번호를 매기시겠습니까?
$ nl -b a abc.txt
내가 아는 한 nl
행 오른쪽에 행 번호를 넣을 수는 없지만 입력의 두 열을 바꾸는 솔루션이 있으므로 문제가 되지 않습니다.
$ paste <(nl abc.txt) <(nl abc.txt) | cut -f 2,3
a 1
b 2
c 3
여기서는 더 이상 구분 기호를 지정할 필요가 없습니다. nl
각 줄의 시작 부분에 공백이 삽입되고 그 뒤에 줄 번호와 탭 문자가 삽입됩니다. paste
열 사이에 탭을 삽입하고 cut
탭을 자르면 작동합니다.
열 사이에 공백을 원하면(이제 탭과 일부 공백이 있음) 이를 | tr -s '\t' ' '
명령에 추가하십시오. 이는 모든 탭 문자를 공백으로 변경("음역")하고 -s
결과로 나오는 연속 공백을 단일 공백으로 "압축"( )합니다.
쉼표와 공백을 원하면 다음을 사용하십시오 | tr '\t ' ', '
.
$ paste <(nl abc.txt) <(nl abc.txt) | cut -f 2,3 | tr -s '\t ' ', '
a, 1
b, 2
c, 3
이는 한 줄에 여러 단어가 포함된 파일에는 작동하지만 탭 문자가 포함된 파일에는 실패합니다.
$ cat abc.txt # no tabs in this file though
a text there is a
b goes hole in my
c here pants
$ paste <(nl abc.txt) <(nl abc.txt) | cut -f 2,3
a text there is a 1
b goes hole in my 2
c here pants 3
답변2
sed '/./=' | sed '/./{N; s/\(.*\)\n\(.*\)/\2 \1/;}'
그러나 awk
더 직접적일 것입니다:
awk '/./ {$0 = $0 " " NR}; {print}'
최소한 하나의 문자가 포함된 줄에만 번호를 매기는 것이 이상해 보입니다. 이것이 의도하지 않은 경우 다음과 같이 변경할 수 있습니다.
sed = | sed 'N; s/\(.*\)\n\(.*\)/\2 \1/'
awk '{print $0, NR}'
답변3
작업을 수행하는 또 다른 방법은 nl
options 와 함께 명령을 사용하는 것입니다 -nln
. 이는 파일의 행에 번호를 매깁니다. 예를 들어..
echo -e "a\nb\nc\n" | nl -nln -
생산 예정:
1 a
2 b
3 c
이제 남은 것은 숫자를 단어 오른쪽으로 옮기는 것뿐입니다. 이는 다음을 sed
사용하여 수행할 수 있습니다.
sed 's/^\([^ \t]*\)[ \t]*\([^ \t].*\)$/\2 \1/g'
그것이 하는 일은 줄의 첫 번째 단어를 찾는 것입니다. (첫 번째 단어를 찾으려면 공백과 탭을 제외한 문자만 포함해야 합니다. 이는 를 사용하여 수행됩니다. [^ \t]
) 공백과 함께 기억합니다 . \1
다음 줄은 부분적 \2
으로 및 로 대체 됩니다 \2 \1
.
그래서 마지막 명령은
cat filename | nl -nln - | sed 's/^\([^ \t]*\)[ \t]*\([^ \t].*\)$/\2 \1/g'