첫 번째 열의 내용을 루프 구조로 바꿉니다.

첫 번째 열의 내용을 루프 구조로 바꿉니다.

변경하려는 첫 번째 열이 있는 파일이 있습니다. 예를 들어 다음 파일이 있습니다(원래 파일에는 여러 열이 있었지만 다음 열은 2개 열로 잘렸으며 파일 끝에 빈 줄이 있을 수 있습니다). ).

테스트.txt:

0 a
2 b  
3 c 
4 d
5 e


첫 번째 열의 내용을 0 -> 2, 2 -> 3, 3 -> 5, 4 -> 0, 5 -> 4로 변경해야 합니다. 최종 파일은 다음과 같습니다.

2 a
3 b
5 c
0 d
4 e


다음과 같이 awk를 사용해 보았습니다.

awk '$1=="0"{$1="2"} $1=="2"{$1="3"} $1=="3"{$1="5"} $1=="4"{$1="0"} $1=="5"{$1="4"};1' test.txt

그러나 awk는 한 줄씩 읽지 않고 필요한 것을 변경하지 않으므로 출력은 다음과 같습니다.

4 a
4 b
4 c
0 d
4 e


내가 필요한 Python, sed, awk 또는 기타 스크립팅 도구로 변환하는 데 도움을 줄 수 있는 사람은 누구라도 환영합니다.

답변1

AWK는 실제로 한 줄씩 읽습니다. next각 할당 후 인쇄 후에 명령문을 추가하면 나머지 코드는 건너뜁니다.

awk '$1=="0"{ $1="2"; print; next }
     $1=="2"{ $1="3"; print; next }
     $1=="3"{ $1="5"; print; next }
     $1=="4"{ $1="0"; print; next }
     $1=="5"{ $1="4"; print; next }1' infile

또는 대신 제어 플래그를 사용하십시오.

awk '!s && $1=="0"{ $1="2"; s=1 }
     !s && $1=="2"{ $1="3"; s=1 }
     !s && $1=="3"{ $1="5"; s=1 }
     !s && $1=="4"{ $1="0"; s=1 }
     !s && $1=="5"{ $1="4"; s=1 }
                  { print; s=0  }' infile

하지만 다음과 같이 모든 작업을 수행할 수도 있습니다.

awk -F'( )' 'BEGIN{ split("2 1 3 5 0 4", map) }
$1!=""{ $1=($1+1 in map)?map[$1+1]:$1 }1' infile

그리고분할(문자열,arryName) 함수map아래와 같이 인덱스와 값으로 명명된 배열을 생성하고 , 배열은 FS를 기준으로 분할됩니다(기본값은 Space/Tabs).

Index        Value
map[<0>+1] -->   2
map[<1>+1] -->   we choice it 1 so it will be unchanged for <1> --> 1
map[<2>+1] -->   3
map[<3>+1] -->   5
map[<4>+1] -->   0
map[<5>+1] -->   4

<#>각도 안의 숫자는 첫 번째 열의 값이고, awk에서 배열의 인덱싱은 0이 아닌 1부터 시작하므로 열 값을 1씩 증가시키고 매핑된 배열에서 해당 값을 가져옵니다.


일반적인 해결책으로(그러나 대부분의 사용자 정의 키/값이 연속적이고 배열 인덱스를 키로 사용할 수 있으므로 위의 솔루션을 계속 사용합니다) 그렇지 않은 경우 다음을 수행할 수 있습니다.

awk -F'( )' 'BEGIN{ len=split("0 2 2 3 3 5 4 0 5 4", map) }
{ for(i=1; i<=len/2; i+=2 ) if($1==map[i]){ $1=map[i+1]; break} }1' infile

답변2

$ awk 'BEGIN{split("1 3 5 0 4",map); map[0]=2} {$1=map[$1]} 1' file
2 a
3 b
5 c
0 d
4 e



답변3

쉘 포함:

while read -r idx rest; do
  case $idx in 
    0) idx=2 ;; 
    2) idx=3 ;; 
    3) idx=5 ;; 
    4) idx=0 ;; 
    5) idx=4 ;;
  esac 
  echo "$idx $rest"
done < test.txt

출력을 원본 파일에 다시 쓰려면 다음 중 하나를 수행하십시오.

tmp=$(mktemp)
while ... < test.txt > "$tmp" && mv "$tmp" test.txt

또는 설치 moreutils하고

while ... < test.txt | sponge test.txt

또는 펄:

perl -pe '
    BEGIN {%map = (0=>2, 2=>3, 3=>5, 4=>0, 5=>4)}
    s{(\d+)}{$map{$1} // $1}e
' test.txt

답변4

GNU sed를 사용하고 확장 정규식 모드를 활성화하세요 -E. 첫 번째 열을 분리하고 시나리오에 따라 패턴 공간을 조정 y///하는 명령을 실행하는 것으로 시작합니다 transliterate(현재는 첫 번째 열만 있음). 그런 다음 원래 행을 호출하고 두 번째 열을 가져와 원래 첫 번째 열을 삭제합니다.

sed -e '
  /^\S\s/!b
  s//&\n/;h
  s/\n.*//
  y/02345/23504/
  G;s/\n.*\n//
' file

2 a
3 b
5 c
0 d
4 e

다른 방법은 다음과 같습니다.

perl -lpe '
  s/^\S\s/
      $& =~ tr[02345]
              {23504}r
  /ex;
' file

또는 라이너로:

perl -lpe 's|^\S\s|$& =~ tr/02345/23504/r|e' file
python3 -c 'import sys
ifile = sys.argv[1]
with open(ifile) as fh:
  for l in fh:
    l = l.strip()
    p = l.find(" ")
    if p == 1:
      f1,rest = l[:p],l[p:];print(f1.translate(f1.maketrans("02345","23504")),rest,sep="")
    else:print(l)
' file

awk -v u="02345" -v v="23504" '
  BEGIN {
    gsub(/./, "&" FS, u)
    gsub(/./, "&" FS, v)
    split(u, a)
    for (i=1; i<=split(v,b); i++)
      c[a[i]] = b[i]
  }
  $1 in c{$1=c[$1]}1
' file

관련 정보