Unix ищет и удаляет переменную (содержит косую черту) из файла

При написании сценария оболочки лучше всего сначала указать проверенные переменные, а имена файлов - в последнюю, чтобы вы могли изменять количество указанных файлов. В вашем случае у вас есть номер столбца, файл с шаблонами в нем и два (или, возможно, больше) имени файла для работы. Итак, запустите свой сценарий Bash с

#!/bin/bash
if [ $# -lt 2 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
    echo ""
    echo "Usage: $0 [ -h | --help ]"
    echo "       $0 COLUMN PATTERNFILE [ FILE(s) ... ]"
    echo ""
    exit 0
fi

. Вышеупомянутое предложение if использует форматирование оболочки POSIX старого стиля и будет работать в тире (и других оболочках POSIX), а также в большинстве оболочки старого образца sh . Смысл в том, что если пользователь не указывает аргументы командной строки или просто -h или - help , сценарий просто печатает короткий текст справки.

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

Затем извлеките необходимые параметры (только один, выше ) и сдвиньте их, чтобы мы могли использовать "$ @" для ссылки на все имена файлов, указанные в командной строке:

column=$1
patternfile="$2"
shift 2

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

Давайте затем используем awk для обработки входных файлов:

awk -v column=$column \
  'BEGIN {
       RS = "[\t\v\f ]*(\r\n|\n\r|\r|\n|)[\t\v\f ]*"
       FS = "[\t\v\f ]*;[\t\v\f ]*"
   }

Обратная косая черта в конце первой строки выше просто сообщает оболочке, что команда продолжается на следующей строке. Также обратите внимание, что здесь нет закрывающей одинарной кавычки ', поэтому приведенные ниже строки фактически являются продолжением параметра строки командной строки, который мы передаем для awk .

Правило BEGIN в awk выполняется до обработки файлов. Вышеупомянутый RS устанавливает разделитель записей в соответствии с любым соглашением о новой строке и включает любые начальные или конечные пробелы в каждой строке. Точно так же разделителем полей является точка с запятой, но включая любые пробелы, окружающие ее. Таким образом, a; b имеет два поля, первое из которых a и второе b , ни одно из которых не имеет пробелов.

Я использую следующую идиому, чтобы отслеживать, какой входной файл обрабатывается:

    FNR==1 { ++filenum }

Если это просто означает, что для самой первой записи в каждом входном файле, который мы обрабатываем, мы увеличиваем переменную filenum . Увеличение неинициализированной переменной аналогично увеличению нуля, поэтому мы получаем 1 для первого входного файла и так далее.

Мы просто хотим запомнить содержимое каждой строки в первом входном файле, нашем файле шаблонов:

    filenum==1 { pattern[$0] }

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

Для остальных файлов мы просто проверяем, соответствует ли (точно) поле $ column (предоставленное скриптлету awk в awk-переменной column ) любому из обнаруженных шаблонов. в первом файле, и если это так, мы печатаем всю запись:

    filenum > 1 && ($column in pattern) { printf "%s\n", $0 }

Выше, $ column имеет другое значение по сравнению со сценарием оболочки. Здесь столбец является переменной, а $ column расширяется до значения столбца -го поля в текущей записи (нулевой столбец - вся запись, тем не мение). Синтаксис foo в массиве - это awkism для проверки того, содержит ли массив ключ foo . Итак, в целом, для второго и последующих входных файлов, если значение поля столбца было указано в первом входном файле, запись печатается. на стандартный вывод.

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

    ' "$patternfile" "$@"

, которые завершают этот скриптлет awk.

2
31.08.2017, 15:23
3 ответа

Withgrep:

grep -Fv -f <(echo "$nt") text1
  • -F- интерпретировать шаблон как список фиксированных строк

  • -v- инвертировать смысл соответствие, для выбора несовпадающих строк

  • -f- получить шаблоны из файла, по одному на строку

Вывод:

/u01/app/fa01/
/u01/app/us1fa01_ps6/
2
27.01.2020, 22:09
$ sed "\#$nt#d" text1 
/u01/app/fa01/
/u01/app/us1fa01_ps6/

sedпозволяет вам использовать произвольный разделитель шаблона, если вы заключаете его в кавычки \.

Это приведет к ошибке , если $ntсодержит какие-либо #символы. В этом случае используйте другой разделитель.

Обратите внимание, что при этом будет удалена строка, содержащая шаблон в любом месте строки.

Чтобы заставить шаблон совпадать по всей строке, используйте

$ sed "\#^$nt\$#d" text1

Здесь нам нужно заключить в кавычки конец -строки -привязки $из оболочки с помощью \$.

0
27.01.2020, 22:09

С GNU sed (не уверен в других реализациях sed ), вы можете использовать \%pattern%, где %— произвольный символ.

Итак, должно работать следующее:

sed "\%$nt%d" text1
0
27.01.2020, 22:09

Теги

Похожие вопросы