Редактирование файла без изменения форматирования

0 Joe [2016-06-03 08:38:00]

У меня есть текстовый файл, содержащий строки и числа. Я хотел бы создать короткий скрипт, который ищет определенную строку, и если строка найдена, она умножает n-й разделитель, разделенный пробелом этой строки, на коэффициент масштабирования и сохраняет все в новый файл.
Мы можем предположить, что в файле будет только одна такая строка, а также что n-й аргумент в этой строке будет числом с плавающей запятой. В идеале программа также сохранит форматирование исходного файла.
Например, для поиска строки "ab ce" и умножения четвертого аргумента этой строки на 2.0:

./prog "ab ce" 4 2.0 inputfile.txt output.txt

inputfile.txt:

ab cd   1.0   2.0       3.0 
ab ce   1.0   2.0       3.0 
ac ce   1.0   2.0       3.0
ac ce   de  ef  1.0   2.0       3.0

output.txt

ab cd   1.0   2.0       3.0
ab ce   1.0   4.0       3.0
ac ce   1.0   2.0       3.0
ac ce   de  ef  1.0   2.0       3.0

Я попытался сделать это с помощью awk (ниже), однако это не сохраняет форматирование, и я подозреваю, что есть более элегантное решение. Может ли кто-то предложить другой подход?

#!/bin/sh

search_string=$1
n=$2
scaling=$3
inputfilename=$4
outputname=$5

awk -vORS= -v scal="$scaling" -v ch="$n" -v inp="$search_string" 'BEGIN {} {if($0 ~ inp){ s = ""; for (i = 1; i < ch; i++) s = s $i " "; print s; print $ch*scal," "; s = ""; for (i = ch+1; i <= NF; i++) s = s $i " "; print s,"\n" } else print $0,"\n" } END{}' $inputfilename>$outputname

formatting awk perl


1 ответ


0 Решение Michael Vehrs [2016-06-03 10:24:00]

Решение с использованием GNU awk:

awk -v pattern="ab ce" -v scale=2.0 -v col=4 -f input.awk inputfile.txt

input.awk:

pattern {
    count = split($0, fields, / +/, seps);
    printf fields[1];
    for (i = 2; i <= count; i++) {
        if (i == col) {
            len = length(seps[col-1] fields[col]);
            printf("%" len ".1f", fields[4] * scale);
        } else {
            printf(seps[i-1] fields[i]);
        }
    }
    print "";
    next;
}
{ print }