IFS= 동안을 사용하여 파일에서 필드를 읽은 다음 필드를 바꾸는 방법

IFS= 동안을 사용하여 파일에서 필드를 읽은 다음 필드를 바꾸는 방법
while IFS=, read -r Q1 Q2 Q3 Q4; do #Reading from a CSV file
Replace Q2 with the string "Nan"    #Replace the second comma separated value with a string 

파일에서 읽은 두 번째 값이 문자열로 바뀌고 변수를 바꾸는 것이 아니라 실제 파일 자체를 변경하는 두 번째 줄을 수행하는 방법을 찾고 있습니다. 나는 sed -i를 사용할 것이라고 생각하지만 특별히 파일에 다시 쓰지 않고 이 작업을 수행하는 더 쉬운 방법이 무엇인지 잘 모르겠습니다.

답변1

구분 기호가 있는 간단한 형식의 파일에는 awk가 편리한 경우가 많습니다.

예를 들어, 입력 파일이 주어지면 foo.txt각 줄에서 쉼표로 구분된 두 번째 필드가 변경되고 나머지는 변경되지 않은 채 그대로 두고 수정된 파일이 인쇄됩니다.

$ awk -F, -v OFS=, '{ $2 = "Nan"; print }' < foo.txt
a,Nan,c,d
e,Nan,g,h

-v FS=,그리고 -v OFS=,입력 및 출력 필드 구분 기호를 쉼표로 설정하고 $2 = ...줄의 두 번째 필드를 수정합니다. 모든 행을 변경하려면 NR == 2테스트를 삭제하면 됩니다.

한 줄(예: 123번 줄)에서만 이 작업을 수행해야 하는 경우 다음을 수행할 수 있습니다.

$ awk -F, -v OFS=, -v line=123 'NR == line { $2 = "Nan" } { print }' < foo.txt

내가 "단순 형식"이라고 말한 것에 유의하세요. 그것이 데이터에 따옴표로 묶인 쉼표가 나타날 수 있는 "쉼표로 구분된" 형식 중 하나라면 awk는 적합한 도구가 아닙니다.

답변2

일반 bash에서는 이 작업을 수행할 수 있습니다(느리고 CSV의 세부 정보를 알지 못합니다).

while IFS=, read -r q1 q2 q3 q4; do
    echo "$q1,NaN,$q3,$q4"
done < inputFile > outputFile

ln inputFile inputFile.bak   # backup input file
mv outputFile inputFile      # overwrite input file

추가 도구를 사용하면 성능과 보안을 얻을 수 있습니다.

ruby -rcsv -e '
  CSV.foreach(ARGV.shift) {|row| row[1] = "NaN"; puts CSV.generate_line row}
' infile > outfile

관련 정보