printf "%.3f" ${개행 문자가 포함된 변수} - 오류\n

printf "%.3f" ${개행 문자가 포함된 변수} - 오류\n

좋다여기나는파일.csv따옴표 안의 숫자:

"0.2"
"0.3339"
"0.111111"

숫자를 소수점 세 자리까지 반올림하려면 다음 솔루션이 효과적입니다.

printf "%.03f\n" $(sed 's/\"//g' file.csv)

sed 's/\"//g' file.csv하지만 이제는 변수로 저장하고 싶습니다.

var_sed=$(sed 's/\"//g' file.csv);
printf "%.03f\n" ${var_sed}

작동하지 않습니다. 출력은 다음과 같습니다

zsh: bad math expression: operator expected at `0.3339\n0.1...'
0.000

그래서 문제 var_sed는 .\nprintf "%.03f\n"

내가 아는 유일한 해결책은 다음과 같습니다.

var_sed=$(sed 's/\"//g' file.csv);
printf "%.03f\n" $(echo ${var_sed})
  1. 어쩌면 더 깨끗한 방법이 있을 수도 있습니다.
  2. printf "%.03f\n"또한 다음과 같은 기능을 추가하고 싶습니다 .
printf_function () { printf "%.03f\n" $1;}

하지만 이것은 작동하지 않습니다.

printf_function () { printf "%.03f\n" $1;};
var_sed=$(sed 's/\"//g' file.csv);
printf_function ${var_sed}

작동하지 않습니다 printf_function $(echo ${var_sed}).

______________________________________________________________

파일을 변수에 저장하려는 이유는 무엇입니까? ______________________________________________________________

sed문제는 실제로 명령을 함수에 넣고 싶다는 것입니다 . 죄송합니다. 문제를 단순화하기 위해 변수로 만들었습니다.

내 스크립트는

sed_01 () { sed 's/\"$// ; s/^\"// ; s/something_else//g' $1;};
printf_03 () { printf "%.03f\n" $1;};
printf_03 "$(sed_01 file.csv)"

아래 설명에서 언급했듯이 bash에서 작동합니다.

산출:

"0.200"
"0.334"
"0.111"

하지만 zsh에서는산출:예:

printf_03: bad math expression: operator expected at `0.3339\n0.1...'
0.000

답변1

printf "%.03f\n" $(sed 's/\"//g' file.csv)

var_sed=$(sed 's/\"//g' file.csv);
printf "%.03f\n" ${var_sed}

이는 숫자를 별도의 인수로 사용하는 토큰화에 의존합니다 printf. 문제는 zsh가 과거의 어리석은 잔재로 자동 토큰화를 포기했으며 변수 확장을 위해 이를 수행하지 않는다는 것입니다. 그러나 어떤 이유에서든 명령 대체를 위해 이 작업을 수행합니다.

명령 대체에서 일반 스칼라 변수에 할당할 때 분할도 없으므로 출력의 줄 바꿈이 sed변수에 저장됩니다.

이것이 바로 코드에서 명령 대체를 사용할 수 있지만 중간 변수는 사용할 수 없는 이유입니다.

변수의 값을 먼저 로드해야 하는 경우(단순히 인쇄용으로 수행하는 것이 아닌 경우) 다음을 고려하십시오.배열(zsh)에 저장합니다.:

lines=("${(f)$(sed 's/\"//g' file.csv)}")
printf "%.03f\n" $lines

readarrayBash에서는 /를 사용할 수 있습니다 mapfile.

mapfile -t lines < <(sed 's/\"//g' file.csv)
printf "%.03f\n" "${lines[@]}"

또는 둘 중 하나에 주로 적용되는 것을 원한다면 다시 단어 분사에 의존해야 합니다.

lines=( $(sed 's/\"//g' file.csv) )
printf "%.03f\n" "${lines[@]}"

괄호에 주목하십시오. 배열을 할당하여 단어 분리가 다시 발생합니다. ("주요"에는 동작에 영향을 미치는 수정에 대한 일반적인 경고가 포함되며 IFS파일 이름 글로빙도 발생합니다.)


그렇다면 다시 AWK를 사용하여 이와 같은 작업을 수행하는 것이 더 쉬울 수도 있습니다.

$ awk '{gsub(/"/, ""); printf "%.03f\n", $1}' file.csv
0.200
0.334
0.111

관련 정보