Редактировать строки CSV двумя способами - PullRequest
1 голос
/ 18 июня 2019

У меня есть скрипт bash, который выводит два столбца CSV.Мне нужно добавить трехзначный номер тех строк второго столбца, которые содержат их, с помощью "f." И оставить остальные строки без изменений.До сих пор я пробовал разные способы, но каждый так или иначе потерпел неудачу.

В основном я пробовал использовать регулярные выражения с первым или вторым столбцом для отделения нужных строк от остальных., но я не могу разделять и добавлять одновременно, не отменяя и не портя процесс.Некоторые команды, которые я использовал до сих пор: $ sed $ cut, а также (вложенные) для циклов, циклы read-while, операторы if / else и if / else / elif и т. Д. Ниже приведено одно из таких (не удалось) решение:

for var1 in "^.*_[^f]_.*"
do
    sed -i "" "s:$MSname::" $pathToCSV"_final.csv"
    for var2 in "^.*_f_.*"
    do
        sed -i "" "s:$MSname:f.:" $pathToCSV"_final.csv"
    done
done

Вот несколько примеров строк:

abc_deg0014_0001_a_1.tif,British Library 1 Front Board Outside
abc_deg0014_0002_b_000.tif,British Library 1 Front Board Inside
abc_deg0014_0003_f_001r.tif,British Library 1 001r
abc_deg0014_0004_f_001v.tif,British Library 1 001v
…
abc_deg0014_0267_f_132r.tif,British Library 1 132r
abc_deg0014_0268_f_132v.tif,British Library 1 132v
abc_deg0014_0269_y_999.tif,British Library 1 Back Board Inside
abc_deg0014_0270_z_1.tif,British Library 1 Back Board Outside

Здесь $ MSname = British Library 1 (так как с разными CSV часть «British Library 1» может измениться)другими словами, что мне нужно удалить / заменить, и поэтому я использую расширение параметра).

Желаемый результат :

abc_deg0014_0002_b_000.tif,Front Board Inside
abc_deg0014_0003_f_001r.tif,f. 001r
…
abc_deg0014_0268_f_132v.tif,f. 132v
abc_deg0014_0269_y_999.tif,Back Board Inside

Если вы присмотритесь, вы заметите, что эти строки также отличаются от остальных на " f"в своем первом столбце (строки, которые не должны иметь" f. "перед своим вторым столбцом, различаются по" a"," b"," y"и" z"соответственно в первом столбце).

Ответы [ 2 ]

0 голосов
/ 18 июня 2019

Вы не используете var1 или var2 для чего-либо, и даже если вы это сделали, циклическое переключение переменных и повторное выполнение sed -i для одного и того же выходного файла крайне расточительно. В идеале вы хотели бы записать все изменения в один sed сценарий и обработать файл только один раз.

Не имея возможности угадать, какие у вас есть строки, отличные от "British Library 1" и требуют ли они различных действий, я бы предложил что-то вроде

sed -i '/^[^,]*_f_[^,_]*,/s/,British Library 1 /,f. /
    s/,British Library 1 /,/' "${pathToCSV}_final.csv"

Обратите внимание, как скрипт sed в одинарных кавычках может быть заключен в несколько физических строк. Первая строка находит любые строки, где последние символы между подчеркиваниями в первом столбце, разделенном запятыми, равны f, и заменяет ",British Library 1 " на ",f. ". (Я внес некоторые коррективы в интервал - надеюсь, они вам пригодятся.) В следующей строке мы просто заменяем любые (оставшиеся) вхождения ",British Library 1 " просто запятой; идея состоит в том, что только строки, которые не соответствуют регулярному выражению в предыдущей строке, будут по-прежнему содержать эту строку, и поэтому нам не нужно делать другое соответствие регулярному выражению.

Это можно легко расширить, чтобы охватить больше шаблонов в одном и том же сценарии sed, вместо многократного циклического повторения файла и перезаписи одного шаблона за раз. Например, если ваша следующая задача - заменить Windsor Palace A либо a., либо ничего, в зависимости от того, содержит ли предпоследнее разделенное подчеркиванием подполе в первом поле a, это должно быть достаточно очевидным:

sed -i '/^[^,]*_f_[^,_]*,/s/,British Library 1 /,f. /
    s/,British Library 1 /,/
    /^[^,]*_a_[^,_]*,/s/,Windsor Palace A /,a. /
    s/,Windsor Palace A /,/' "${pathToCSV}_final.csv"

Более подробно, регулярное выражение говорит

^       beginning of line
[^,]*   any sequence of characters which are not a comma
_f_     literal characters underscore, f, underscore
[^,_]*  any sequence of characters which are not a comma or an underscore 
,       literal comma

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

Наконец, обратите внимание, как мы всегда используем двойные кавычки вокруг переменных, которые содержат имена файлов. Есть сценарии, где вы можете избежать этого, но вы должны знать, что вы делаете; простое и понятное правило - всегда ставить двойные кавычки вокруг переменных. Для полной информации см. Когда обернуть кавычки вокруг переменной оболочки?

0 голосов
/ 18 июня 2019

С помощью awk вы можете посмотреть на первое поле, чтобы увидеть, соответствует ли оно "3digits + 1 letter", затем напечатать с f. в этом случае и просто удалить поля 2,3 и 4 в другом случае. Например:

awk -F'[, ]' '{
   if($5 ~ /.?[[:digit:]]{3}[a-z]$/) {
      printf("%s,f. %s\n",$1,$5)} 
   else {
      printf("%s,%s %s %s\n",$1,$5,$6,$7)
   }
 }' test.txt

На приведенном вами примере он дает:

abc_deg0014_0001_a_1.tif, Передняя панель снаружи

abc_deg0014_0002_b_000.tif, Передняя панель внутри

abc_deg0014_0003_f_001r.tif, ф. 001R

abc_deg0014_0004_f_001v.tif, ф. 001v

abc_deg0014_0267_f_132r.tif, ф. 132R

abc_deg0014_0268_f_132v.tif, ф. 132v

abc_deg0014_0269_y_999.tif, Задняя панель внутри

abc_deg0014_0270_z_1.tif, Задняя панель снаружи

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...