Назначение вывода команды переменной оболочки и получение размера переменных - PullRequest
1 голос
/ 27 апреля 2011

У меня есть файл, состоящий из цифр.Обычно каждая строка содержит одно единственное число.Я хотел бы посчитать количество строк в файле, которые начинаются с цифры «0».Если это так, то я хотел бы выполнить некоторую постобработку.

Хотя я могу правильно получить соответствующие номера строк, общее количество найденных строк не является правильным.Ниже я публикую код, который я использую.

linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile});
# linesToRemove=$(grep -n "^0" ${inputFile} | cut -d":" -f1);

linesNr=${#linesToRemove} # <- here, the error
# linesNr=${#linesToRemove[@]} # <- here, the error

if [ "${linesNr}" -gt "0" ]; then
    # do something here, e.g. remove corresponding lines.
    awk -v n=$linesToRemove 'NR == n {next} {print}' ${anotherFile} > ${outputFile}
fi

Кроме того, что касается команды на основе awk, как я могу использовать переменную оболочки?Я попробовал команду ниже, но она не работает правильно, так как myIndex интерпретируется как текст, а не как переменная.

linesToRemove=$(awk -v myIndex="$myIndex" '/^myIndex/ { print NR;}' ${inputFile});

Учитывая номера строк, начинающиеся с 0, найденные в ${inputFile}Я хотел бы удалить номера соответствующих строк из ${anotherFile}.Пример для $ {inputFile} и $ {anotherFile} приведен ниже:

// ${inputFile}
0 
1
3
0

// ${anotherFile}
2.617300e+01 5.886700e+01 -1.894697e-01 1.251225e+02
5.707397e+01 2.214040e+02 8.607959e-02 1.229114e+02
1.725900e+01 1.734360e+02 -1.298053e-01 1.250318e+02
2.177940e+01 1.249531e+02 1.538853e-01 1.527150e+02

// ${outputFile}
5.707397e+01 2.214040e+02 8.607959e-02 1.229114e+02
1.725900e+01 1.734360e+02 -1.298053e-01 1.250318e+02

В приведенном выше примере мне нужно удалить строки 0 и 3 из ${anotherFile}, учитывая, чтоэти строки соответствуют строкам, начинающимся с 0 в ${inputFile}.

Ответы [ 5 ]

1 голос
/ 27 апреля 2011

Я думаю, что вы должны сделать следующее, чтобы назначить массив:

linesToRemove=( $(awk '/^0/ { print NR; }' ${inputFile}) )

И чтобы получить количество элементов, которые вы делаете (как у вас в прокомментированной строке):

linesNr=${#linesToRemove[@]}

Чтобы удалить строки из файла, вы можете сделать что-то вроде:

sedCmd=""
for lineNr in ${linesToRemove[@]}; do
  sedCmd="$sedCmd;${lineNr}d"
done
sed "$sedCmd" ${anotherFile} > ${outputFile}
1 голос
/ 27 апреля 2011

Если вы хотите посчитать количество строк в файле, который начинается с 0, то эта строка неверна.

linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile});

Выше указано, что нужно печатать номер строки, когда строка начинается с 0, а ваша переменная linesToRemove будет содержать все номера строк, а не общее количество строк. Используйте блок END{}, чтобы получить общее количество. например,

linesToRemove=$(awk '/^0/ {c++}END{print c}' ${inputFile});

Что касается вашего второго вопроса об использовании переменной внутри awk, используйте оператор регулярного выражения ~. А затем установите переменную myIndex для включения ^ якоря

linesToRemove=$(awk -v myIndex="^$myIndex" '$0 ~ myIndex{ print NR;}' ${inputFile});

наконец, если вы просто хотите удалить те строки, которые начинаются с 0, просто удалите их

awk '/^0/{next}{print $0>FILENAME}' file 

Если вы хотите удалить строки из другого файла, используя то, что записано во входном файле, вот один из способов

paste -d"|" inputfile anotherfile | awk '!/^0/{gsub(/^.*\|/,"");print}'

Или только одна awk команда

awk 'FNR==NR && /^0/{a[FNR]} NR>FNR && (!(FNR in a))' inputfile anotherfile

грубое объяснение: FNR == NR && / ^ 0 / означает, что вся первая строка файла начинается с 0 и помещается в строку a. NR>FNR означает обработку следующего файла и, если номер строки отсутствует в массиве, выведите строку. См. Документацию gawk, что означает FNR, NR и т. Д.

0 голосов
/ 27 апреля 2011

Учитывая большое количество правок в этом вопросе, кажется, проще всего начать новый ответ. Ваша проблема может быть решена простым однострочником:

$ sed "$( grep -n ^0 $inputFile | sed 's/:.*/d;/g' )" $anotherFile > $outputFile
0 голосов
/ 27 апреля 2011

Это в значительной степени зависит от выполняемой вами постобработки, но вам действительно нужен фактический счет? Почему бы не сделать что-то вроде этого:

if grep ^0 $inputfile > /dev/null; then
  # There is at least one line with a leading 0
  :
fi

grep -v ^0 $inputfile | process-lines-without-leading-zero
grep ^0 $inputfile | process-lines-with-leading-zero

Или даже просто:

if grep ^0 $inputfile | process-lines-with-leading-zero; then
  # some post processing
  :
fi

- EDIT -

Исходя из того, что вы сказали в своем комментарии, я бы порекомендовал другой подход. Если я вас правильно понимаю, вы хотите прочитать файл a, ища строки вида ^ 0 [0-9] *, а затем удалите эти номера строк из файла б. Делать это по одной строке довольно медленно, если файлы становятся большими. Просто сделай:

cmd=$( grep '^0[0-9]*$' a | sed 's/$/d;/g' )
sed "$cmd" b

Назначение cmd формирует команду sed для удаления строк. Вызов sed на b пропустит эти строки. Вам нужно будет соответствующим образом перенаправить вывод sed (возможно, во временный файл и затем вернуться к b, или просто использовать 'sed -i', если вы используете gnu sed.)

0 голосов
/ 27 апреля 2011

Обычно, если вы делаете это:

linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile});

вместо этого:

linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile});
linesNr=${#linesToRemove}

используйте это:

linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile});
linesNr=${echo $linesToRemove|awk '{print NF}'}

POC:

cat temp.sh
#!/usr/bin/ksh

lines=$(awk '/^d/{print NR}' script.sh)
nooflines=$(echo $lines|awk '{print NF}')
echo $nooflines
torinoco!DBL:/oo_dgfqausr/test/dfqwrk12/vijay> temp.sh
8
torinoco!DBL:/oo_dgfqausr/test/dfqwrk12/vijay>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...