홀수 열에만 음수를 사용하여 수평 및 수직으로 무한히 계속되는 다음 데이터 프레임이 있습니다.
-1 2 3 4 -5 9
2 3 -4 5 -6 11
나는 두 번째, 네 번째, 여섯 번째 전체 열(또는 모든 짝수 열)을 원하고 마이너스 기호는 첫 번째, 세 번째, 다섯 번째(또는 모든 홀수 열)에서만 원하므로 다음과 같은 결과를 얻습니다.
- 2 4 - 9
3 - 5 - 11
마침내 다음과 같은 결과를 얻었습니다.
-2 4 -9
3 -5 -11
따라서 동일하게 유지하려면 짝수 열의 값이 필요하고 홀수 열의 값은 음수 값이 있으면 그대로 유지하고 양수 값이 있으면 폐기합니다.
awk/sed를 사용하여 이를 수행할 수 있는 방법이 있습니까?
제가 아는 한 대략 이렇습니다.
awk '{ for (i=2;i<=NF;i+=2) $i="" }1' FILE.txt | sed 's/[0-9,.]*//g'
답변1
방법 sed
:
sed -E '
s/^(([ \t]*-?[ \t]*[0-9.]+[ \t]+[0-9.]+)*)[ \t]+-?[ \t]*[0-9.]+$/\1/;
s/[0-9.]+[ \t]+([0-9.]+)/\1/g'
산출:
-2 4 -9
3 -5 -11
열 수가 홀수인 경우 첫 번째 표현식은 후행 열을 제거합니다. <number> <number>
첫 번째 숫자가 음수일 수 있는 0개 이상의 쌍을 찾아서 이를 수행합니다 .
편집하다:sed
@mikeserv에서 영감을 받은 더 짧은 솔루션:
sed -E '
s/[0-9.]+[ \t]*([0-9.]*)/\1/g;
s/[- \t]*$//'
똑같은 것 perl
:
perl -lpe 's/^((\s*-?\s*[\d.]+\s*[\d.]+)*)\s+-?\s*[\d.]+$/$1/o; s/[\d.]+\s+([\d.]+)/$1/g'
다른 방법 perl
(아마도 가장 깨끗한 방법):
perl -lpe '$a = 1; s/([\d.]+\s*)/$a++ % 2 ? "" : $1/eg; s/[-\s]*$//o'
답변2
하나씩 perl
:
$ perl -anle 'BEGIN{$,=" "}
print map{$_=$F[$_]=~/^-/?"-$F[$_+1]":" $F[$_+1]"}grep{!($_%2)}0..$#F' file
-2 4 -9
3 -5 -11
-an
@F
입력을 배열 로 분할BEGIN{$,=" "}
출력 필드 구분 기호를 공백으로 설정grep{!($_%2)}0..$#F
배열의 모든 짝수 인덱스를 가져옵니다@F
. 즉, 홀수 요소의 인덱스를 가져옵니다.map{$_=$F[$_]=~/^-/?"-$F[$_+1]":" $F[$_+1]"}
홀수 요소가 시작하는지 확인한-
후 다음 짝수 요소에 추가하고-
그렇지 않으면 공백을 추가합니다.
답변3
@terdon 님처럼답변하지만 sed가 없으면:
awk '{ for(i=1;i<=NF;i+=2){
if ($i<0) $(i+1)*=-1;
$i = "";
}
print
}'
답변4
한 가지 방법은 다음과 같습니다.
$ awk '{for(i=1;i<=NF;i+=2){if($i<0){$i="-"}else{$i="";} }};1' file |
sed 's/- */-/g; s/ */ /g'
-2 4 -9
3 -5 -11
스크립트 awk
는 모든 홀수 열을 반복하여 -
해당 값이 음수이면 값을 설정하고, 그렇지 않으면 null로 설정합니다. 그런 다음 sed
a 뒤의 모든 공백을 제거 -
하고 여러 개의 연속 공백을 단일 공백으로 바꿉니다. 이는 일부 필드에 두 개 이상의 문자가 포함되고 다른 필드에는 하나의 문자가 포함되므로 정렬이 깨짐을 의미합니다. 문제가 되지 않는 필드를 사용했다면 보기에 좋지 않을 뿐입니다.