행과 열이 많은 대용량 파일이 있습니다. 내용의 값은 -2와 2 사이입니다. 절대값보다 작은 값을 0으로 바꾸고 싶습니다. 예를 들어 -0.3이나 0.6(절대값 0.3과 0.6)이 있다면 이를 0으로 바꾸고 싶습니다. 누구든지 이 작업을 수행하는 좋은 방법을 알고 있습니까?
답변1
perl -pe 's/\S+/abs($&) < 1 ? 0 : $&/ge' < your-file
여기서 등의 숫자는 perl
허용되지만 16진수 또는 기타 기호는 허용되지 않습니다(0x12는 0으로 처리되고, 010은 8이 아닌 10으로 처리됨).0.123
-12e-4
예:
$ echo "1.2 120e-4 0.001e4 -0.2" | perl -pe 's/\S+/abs($&) < 1 ? 0 : $&/ge'
1.2 0 0.001e4 0
답변2
awk '{
for (i=1; i<= NF; i++) {
if($i < 1 && $i > -1) { $i=0; }
}
print }' file
...awk를 사용하여 가져옵니다.
sed 사용(두 표현식을 이 순서로 유지하지 않도록 주의하세요. 그렇지 않으면 음수 0이 됩니다):
sed -e 's/-0\.[0-9]*/0/g' -e 's/0\.[0-9]*/0/g' file
재미를 위해 bash에 솔루션 추가:
#!/usr/bin/env bash
# for extended pattern matching, to grab repeated [:digits:]
shopt -s extglob
# to prevent filename globbing
set -f
while read line
do
# specifically left $line unquoted to allow splitting
for f in $line
do
f=${f/-0.*([[:digit:]])/0}
f=${f/0.*([[:digit:]])/0}
printf "%s " $f
done
printf "\n"
done
이렇게 하면 각 줄에 후행 공백이 추가됩니다. 이를 파이프하여 sed 's/ $//'
후행 공백을 제거합니다.
...더 많은 재미를 위해 (bash-isms를 사용하지 않고) 쉘/grep 솔루션을 추가합니다.
set -f
while read line
do
# specifically left $line unquoted to allow splitting
for f in $line
do
echo $f | grep -q -E -- '-?0\.[[:digit:]]'
if [ $? -eq 0 ]
then
printf "0 "
else
printf "%s " $f
fi
done
printf "\n"
done
이 -q
플래그는 grep의 출력을 침묵시킵니다. 우리가 원하는 것은 반환 코드뿐입니다. 이 -E
플래그는 "[0-9]" 대신 "[:digit:]"를 활성화합니다. 이는 또한 각 줄에 후행 공백을 추가하여 sed 's/ $//'
후행 공백을 제거합니다.
답변3
앗
awk '{ for(i=1;i<=NF;i++)if(sqrt($i^2)<1){printf "0 "}else{printf "%s ", $i}print ""}'
원하는 대로 작동해야 합니다. (그러나 이식성이 없으며 sqrt()에 대한 불필요한 호출이 포함되어 있습니다. Jeff Schallers의 답변이 더 좋습니다.)
-loop는 for
테이블 열을 반복하며, sqrt($i^2) <1
조건( sqrt(x*x)
또는 sqrt(x^2)
결과는 x의 절대값)이었습니다. 0
절대값이 작으면 if-else 부분이 인쇄되고 0.6
, 값이 더 크면 인쇄됩니다 $i
.
이것이 당신이 원하는 것이기를 바랍니다.
노트
다른 필드 구분 기호를 원할 경우 ' '
추가 옵션을 추가해야 합니다.
AWK 매뉴얼 페이지 - http://www.staff.science.uu.nl/~oostr102/docs/nawk/nawk_23.html