변경하려는 첫 번째 열이 있는 파일이 있습니다. 예를 들어 다음 파일이 있습니다(원래 파일에는 여러 열이 있었지만 다음 열은 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