awk를 사용하여 열 재정렬


13

csv 파일의 7 번째 열을 사용하여 끝으로 이동하려고합니다

awk -F '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}',OFS= "$file"

여기서 $ file은 디렉토리의 .csv 파일입니다. 그러나 출력은

awk:                          ^ syntax error

누구 든지이 오류를 해결하는 방법을 알고 있습니까?


7
awk 오류를 표시 할 때 전체 내용을 표시해야합니다. 는 ^오류가 발생 된 명령의 특정 부분을 나타냅니다.
terdon

답변:


11

-F옵션은 인수를 필요 : -F,예를 들면.

awk스크립트 의 끝은 나머지 매개 변수와 함께 (공백 문자) 로 분리해야합니다 .

필드 구분 기호가 ,있고 유지하려는 경우 열 수가 일정하고 11보다 작거나 같은 경우 다음을 시도하십시오.

awk -F, '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' OFS=, "$file"

8
@anuribs 프로그램이 허용하는 프로그램은 거의 없습니다. 표준 방법은 command file > newfile && mv newfile file입니다. 즉, awk이것을 지원하는 최신 버전의 GNU : gawk -i inplace '{blah blah}' file.
terdon

1
또는 대신 mv newfile file사용할 수 있습니다 cat newfile > file ; rm -f newfile.-의 inode 및 권한이 유지 file됩니다.
cas

일반적으로 mktemp임시 파일 이름을 스크립트로 하드 코딩 하는 대신 사용하는 것이 좋습니다 . 예tf=$(mktemp) ; command file > "$tf" ; cat "$tf" > file ; rm -f "$tf"
cas

8

더 짧은 해결책은

awk -F',+' -v OFS=, '{$(NF+1)=$7; $7=""; $0=$0; $1=$1}1' file

,+모든 awk버전 에서 작동 하는지 확실하지 않지만 최소한 GNU awk에서도 작동하며 -compatibility 모드 에서도 작동합니다.

설명:

  • $(NF+1)=$7: 먼저 우리는 줄의 끝에 7 번째 필드를 추가합니다 ( $12=$7이 경우 가능)
  • $7="": 다음 단계에서 7 번째 필드가 지워집니다 (그러나 주변 구분 기호는 그대로 유지됨)
  • 삭제 구분으로하여 (통해 재 설정 한 전체 녹화해야 $0=$0(이 통해 이루어진다 필드 분리 여러개 쉼표 처리) -F',+'여기서, +하나 개 또는 그 이상을 의미한다), 또한 통해 현재 레코드를 재 배열 $1=$1이전에 설정된 출력 필드를 사용하여 광고를 다시 강제 구분 기호 (옵션으로 설정 -v OFS=,)
  • 모든 셔플 링이 완료된 후 결과를 인쇄 할 준비가되었습니다 1

입력 예 :

1,2,3,4,5,6,7,8,9,10,11

산출

1,2,3,4,5,6,8,9,10,11,7

다른 열이 비어 있으면 어떻게됩니까? 그러나 예, FS는 POSIX의 정규 표현식이므로 여러 문자 ,+일 경우 작동합니다.
Random832

(1) 입력 데이터의 일곱 번째 열을 "사라지게"하는 것이 아니라 단순히 널로 설정하는 것이이 문제의 까다로운 부분이라는 것을 이해합니다. 그러나 Random832가 말한 것처럼 솔루션은 빈 열을 클로버합니다 (예 : all,ball,call,,,fallall,ball,call,fall). (2)  $(NF+1)=$7는 영리한 접근법입니다. IMHO $0 = $0 OFS $7는 조금 더 명확하고 두 글자 만 길며 같은 일을하는 것처럼 보입니다. $0 = $0 OFS $7코드와 동일하지 않은 상황을 생각할 수 있습니까 ?
G-남자 '는 분석 재개 모니카'말한다

@ Random832 @ G-Man 예, 빈 필드, 빈 줄 또는 NF <7과 같은 일부 가장자리는 별도로 처리하거나 코드를 다시 정렬해야합니다. 이것은 모든 일반적인 경우에 대해 "완벽한 솔루션"이 아닌 아이디어 일뿐입니다. $0=$0 OFS $7아마 동일 $(NF+1)=$7하지만 나머지 코드는 변경되지 않고 일반적으로 변경되지 않습니다.
jimmij

5

를 사용하여 인쇄하는 경우 OFS=필드 사이에 구분 기호가 없으면 간단히 값을 $7변수에 저장하고 $7비우기로 설정 하고 행과 변수를 직접 인쇄하면됩니다. 모든 필드를 지정할 필요는 없습니다.

$ cat file
1,2,3,4,5,6,7,8
$ awk -F, -vOFS= '{k=$7; $7=""; print $0,k}' file 
12345687


3

당신은 특별히 awk 를 사용하고 싶다고 말하지 않았고 에서 제공 한 것처럼 내부 편집을 사용하고 싶다고 말 sed -i했으므로 여기에 sed -i변형이 있습니다. 일반적 awk으로 열을 사용하는 것이 더 좋지만 sed자연스럽게 임의의 수의 열을 처리하기 때문에 선호하는 경우 입니다.

MOVECOL=7
N=$((MOVECOL-1))
sed -r -e "s/^(([^,]*,){$N})([^,]*),(.*)/\1\4,\3/" -i test.csv

설명:

  • -r 확장 정규 표현식을 선택하여 많은 백 슬래시를 피합니다.
  • 첫 번째 그룹은 쉼표로 끝나는 문자열의 $ N 반복, 즉 마지막으로 쉼표로 이동하려는 열 앞의 열입니다.
  • 두 번째 그룹은 $ N 번째 반복입니다.
  • 세 번째 그룹은 마지막 쉼표없이 이동하려는 열입니다.
  • 네 번째 그룹은 이전에 쉼표없이 이동하려는 열 이후의 모든 열로 구성됩니다.
  • 첫 번째 그룹, 마지막 그룹 및 추출한 열로 바꾸고 필요에 따라 쉼표를 삽입합니다.

물론 이것은 따옴표로 쉼표를 숨기는 파일 (또는 더 나쁘게 탈출)에서는 작동하지 않지만 awk는 심각한 곡예가 없으면 처리하지 않습니다. 당신은 그 문제가있는 경우가 더 나을 것 perl모듈 Text:CSV또는 python모듈 csv.


2

몇 가지 awk변형 (파일이 변수 안에 있다고 가정 $file)

  • 여기에서 모든 열량을 순환하고 필드 구분 기호 (OFS)로 인쇄하고 줄 끝에서 레코드 종결 자 (ORS)를 인쇄 할 수 있습니다.

    awk  -F',' -v OFS=,                                \
    '{for(i=1;i<=NF;i++) if (i!=7) printf "%s",$i OFS; \
    printf "%s",$7;printf ORS}' "$file"
  • 여기에 정규식과 gensub()함수 를 사용하여

    gawk -F',+' -v OFS=, '{$0=gensub(/\s*\S+/,"",7) OFS $7}1' "$file"

    7 번째 필드를 죽이고 줄의 끝에 그것을 인쇄하십시오.

    • $0 전체 기록이다
    • $nn 번째 레코드입니다
    • NF 현재 줄의 필드 수
    • OFS 출력 된 구분 기호
    • ORS 출력 레코드 종결 자
    • 1awk라고 말하고 true기본값 ( $0)을 인쇄 하는 트릭 입니다.

업데이트 ...

거의 잊어 버렸습니다 .7 번째 행을 따라 모든 열을 이동할 수 있습니다 .

awk  -F',' -v OFS=, '{tmp=$7; for(i=7;i<=NF;i++) $i=$(i+1); $NF=tmp}1 ' "$file"

(1) 논란의 여지는 OFS $7보다 더 강력한 것입니다 "," $7. (2) ", " $7OP가 쉼표 뒤에 공백을 원하지 않는다는 질문이 나타내는 한, 나는 이것이 잘못 되었다고 생각 합니다. (그리고 입력 데이터에 쉼표 뒤에 공백 $7이 있으면 이미 공백으로 시작하고 추가 공백을 추가 할 것입니다.)
G-Man은 'Reinstate Monica'라고 말합니다.

@ G-Man 주로 아이디어, 변형을 제안하는 것이 었습니다. 덕분에, 자리, 나는 약 동의 OFS $7뿐만 아니라 더 강력하지만 더 일반적인 ( "서둘러 폐기물한다" )
Hastur
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.