2016-06-03 3 views
0

У меня есть текстовый файл, содержащий строки и цифры. Я хотел бы создать короткий скрипт, который ищет определенную строку, и если строка найдена, она умножает n-й разделитель, разделенный пробелом этой строки, на коэффициент масштабирования и сохраняет все в новый файл.
Мы можем предположить, что в файле будет только одна такая строка, а также что n-й аргумент в этой строке будет числом с плавающей запятой. В идеале программа также сохранит форматирование исходного файла.
Например, для поиска строки "абы с" и умножать четвертый аргумент этой линии от 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 
+0

Вы можете упростить 'awk' сценарий значительно: ' awk '/ ab ce/{$ 4 = $ 4 * 2.0} {print}' ' –

ответ

0

Решение с использованием 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 } 
+0

Это сработало отлично для меня после нескольких изменений: – Joe

+0

Я изменил строку 1: $ 0 ~ pattern {и строка 7: поля [col]. Также кажется, что требуется более новая версия awk, поскольку она не работает с 3.1.7, создавая ошибку awk: input.awk: 2: fatal: 4 недопустимо как количество аргументов для split. Однако он работает с 4.1.3. Благодаря! – Joe

0

Решение в Perl:

$search_string = $ARGV[0]; 
$index = $ARGV[1]; 
$inc_val= $ARGV[2]; 
open($in,"<",$ARGV[3]); 
open($out,">",$ARGV[4]); 


while($line = <$in>) 
{ 
    chomp($line); 
    if($line =~ /$search_string/) 
    { 
    @temp = split('\s+',$line); 
    $old_val = $temp[$index-1]; 
    $new_val = sprintf("%.1f", $old_val*$inc_val); 
    $line =~ s/$old_val/$new_val/; 
    } 
    push(@temp_arr,$line); 
} 


print $out join("\n",@temp_arr); 
+0

Спасибо! Кажется, это дает правильное форматирование, если «% .1f» соответствует точности редактируемого номера, а измененное число содержит то же количество цифр после умножения. – Joe

+0

@ Joe, приятно это слышать. Если этот ответ или любой другой ответ помогли вам, пожалуйста, подтвердите/примите ответ. – SilentMonk

Смежные вопросы