입력 파일은 다음과 같습니다.
1 0 0 000 3444
2 3 3 456 6875
3 0 0 023 3300
4 2 2 211 1000
첫째: 각 행에 대해 2개의 복사본을 원합니다.
1 0 0 000 3444
1 0 0 000 3444
2 3 3 456 6875
2 3 3 456 6875
3 0 0 023 3300
3 0 0 023 3300
4 2 2 211 1000
4 2 2 211 1000
둘째: 각 행의 첫 번째 복사본에서 3은 2로 바뀌고 4는 1로 바뀌어야 하며, 각 행의 두 번째 복사본에서는 3이 1로 바뀌고 4가 2로 바뀌어야 합니다(첫 번째 열은 행 이름) 및 행 번호는 변경되어서는 안 됩니다). 따라서 최종 출력은 다음과 같습니다.
1 0 0 000 2111
1 0 0 000 1222
2 2 2 156 6875
2 1 1 256 6875
3 0 0 022 2200
3 0 0 021 1100
4 2 2 211 1000
4 2 2 211 1000
어떤 제안이 있으십니까? 나는 이것을 시도했지만 작동하지 않습니다.
awk '
{ tmp = $2; gsub("3", "2", $2); gsub("4", "1", $2); print}
{ $2 = tmp; gsub("3", "1", $2); gsub("4", "2", $2); print}
' < input > output
답변1
각 행을 두 배로 늘리는 방법:이봐...
두 번째 요청의 경우 첫 번째 필드와 전체 행을 변수에 저장한 다음 첫 번째 변경을 수행하고 첫 번째 필드를 초기 값으로 설정하고 인쇄한 다음 행 내용을 복원하고 두 번째 변경을 수행합니다. 첫 번째 필드를 다시 초기 값으로 설정하고 인쇄합니다.
awk '{t=$1;l=$0;gsub(/3/, "2");gsub(/4/, "1");$1=t;print}
{$0=l;gsub(/3/, "1");gsub(/4/, "2");$1=t;print}' infile
답변2
Perl에는 다음과 같은 기능이 내장되어 있으므로 이런 종류의 작업에 매우 적합한 것 같습니다.tr
$ perl -alne '
@tmp=@F;
tr/34/21/ for @tmp[1..4]; print join " ", @tmp;
tr/34/12/ for @F[1..4]; print join " ", @F
' file
1 0 0 000 2111
1 0 0 000 1222
2 2 2 156 6875
2 1 1 256 6875
3 0 0 022 2200
3 0 0 021 1100
4 2 2 211 1000
4 2 2 211 1000
답변3
매우 우아하지는 않지만 GNU를 사용하면 가능합니다 sed
.
h # save in hold
s_^[0-9]\{1,\} __ # remove first column
s_3_A_g # change 3 and 4 to A and B
s_4_B_g
x # swap with hold
s_ .*$__ # remove everything but first column
G # append from hold
s_\n_ _ # join lines (with space)
h # save in hold space again
s_A_2_g # first output -> 2, 1
s_B_1_g
p # print first line
g # restore from hold
s_A_1_g # second output -> 1, 2
s_B_2_g
# end of script, second line printed automatically
이렇게 하면 첫 번째 열이 저장되고(변경되지 않음) 나머지 3과 4가 각각 As와 B로 변경된 행 버전이 작성됩니다. 그런 다음 이 라인은 두 가지 출력 모두에 사용됩니다. 먼저 2
합계를 사용한 1
다음 그 반대로 사용합니다.
sed -f script.sed input > output
이는 입력 내용에 숫자와 공백만 포함되어 있다고 가정합니다. A
그리고 B
아직 거기에 없습니다.