Скопируйте указанные c символов из первых двух строк текстового файла в переменные - PullRequest
1 голос
/ 11 марта 2020

У меня есть несколько тысяч текстовых файлов, которые мне нужно переименовать. Мне может понадобиться делать это время от времени, поэтому я хотел бы создать скрипт bash для этой задачи. Новое имя файла должно быть создано из некоторых символов из первой строки, а некоторые из второй строки. Пример содержимого:

Record #123987. More stuff .here
Something 'I need this string' blah blah
More lines of info
....

Можете ли вы помочь мне скопировать номер записи из строки 1 и текст между одинарными кавычками из строки 2 в переменные, чтобы я мог l oop просмотреть файлы и переименуйте их, используя переменные.

Причина, по которой я указываю c в отношении номеров строк, заключается в том, что в одинарных кавычках может быть больше информации, а также больше «#» и «.» в других местах текста.

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

Спасибо

Ответы [ 4 ]

2 голосов
/ 12 марта 2020

Передайте вывод этой команды в оболочку:

$ awk '
    FNR==1 { recno=$2; gsub(/[^0-9]/,"",recno) }
    FNR==2 { sub(/[^\047]+\047/,""); sub(/\047.*/,""); gsub(/[[:space:]]+/,"_");
             printf "mv -- \047%s\047 \047%s_%s\047\n", FILENAME, $0, recno
           }
' file
mv -- 'file' 'I_need_this_string_123987'

Если вы используете GNU awk, вы можете добавить nextfile в отдельной строке после print для эффективности.

2 голосов
/ 12 марта 2020

Допущения:

  • в строке 1 всегда есть нужные данные между первым набором га sh (#) и периодом (.)
  • строка 2 всегда есть нужные данные между первым набором одинарных кавычек (')
  • нам не нужно беспокоиться о каких-либо проблемах, упомянутых @LukeH в комментариях (я не говорю, что это не должно Это не считается, но это немного излишне, если OP не может подтвердить ничего лишнего - контрольные символы, экранированные символы и т. д. c - в полях, которые мы ищем)

One awk решение, которое извлекает нужные данные из первых двух строк файла:

awk -F"[#.']" '
NR<=2 { printf "%s ",$2 ; next }
NR>=3 { exit }
' <filename>

Где:

  • -F"[#.']" - использовать 3 разных разделителя (га * 1044) *, точка, одинарная кавычка)
  • NR<=2 ... - для первых 2 строк файла печатное поле # 2; используйте printf и не '\ n', чтобы 2 поля печатались в одной строке
  • NR>=3 ... - не интересует остальная часть файла, поэтому exit обработка

Для данного примера:

$ cat record.dat
Record #123987. More stuff .here
Something 'I need this string' blah blah
More lines of info
....

$  awk -F"[#.']" 'NR<= 2 { printf "%s ",$2 ; next } NR>=3 {exit} {print $0}' record.dat
123987 I need this string

Теперь мы можем подать эти результаты в команду read, чтобы захватить наши 2 поля в 2 переменные:

$ read -r a b < <(awk -F"[#.']" 'NR<= 2 { printf "%s ",$2 ; next } NR>=3 {exit} {print $0}' record.dat)

И показать что 2 переменные были правильно заполнены:

$ echo ":$a:$b:"
:123987:I need this string:
2 голосов
/ 12 марта 2020

Вот мое мнение. Обратите внимание, что это не сработает во второй строке, если строка в кавычках могла выйти за пределы кавычек. например, 'Don\'t worry about apostrophes'

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

for file in "$@"; do
    record=$(sed -rn '1s/^Record[ \t]+#([0-9]+).*/\1/p' "$file")
    quoted=$(sed -rn "2s/^[^']+'([^']+).*/\1/p" "$file")
    echo $record $quoted
done

Я использую sed для замены всех, кроме цифр, найденных после ha sh в строке 1. Затем я использую ту же технику для поиска всего в первом наборе цитат в строке 2.

Регулярные выражения

  • / ^ Запись [\ t] + # ([0-9] +). * /

    Совпадение со словом «Запись» в начале строки, за которым следуют одна или несколько вкладок или пробелов, после которых следует ha sh, за которыми следуют одна или несколько цифр, затем что угодно. Извлечь цифры.

  • / ^ [^ '] +' ([^ '] +). * /

    Совпадение с одним или несколькими не кавычками символов в начале строки, затем одиночная кавычка, затем извлеките все до (но не включая) следующей кавычки.

1 голос
/ 12 марта 2020

Попробуйте это:

Допущения:
1. Номер записи - это первое вхождение строки между "#" и "." в строке 1
2. Текст находится между первым набором одинарных кавычек в строке 2 (и поэтому не будет обрабатывать апострофы)

    $ cat > foo.txt
    Record #123987. More stuff .here
    Something 'I need this string' blah blah
    More lines of info
    ....

    $ cat > foo2.txt
    Record #987321. More stuff .here
    Something 'I need this string too' blah blah
    More lines of info
    ....

    $ for file in *.txt
    > do
    > var1=`sed -n 1p $file | awk -F "#" '{print $2}' | awk -F"." '{print $1}'`
    > var2=`sed -n 2p $file | awk -F "'" '{print $2}'`
    > echo "Variable1="$var1 " and Variable2="$var2
    > done

Вывод:

    Variable1=987321  and Variable2=I need this string too
    Variable1=123987  and Variable2=I need this string
...