сделайте вывод grep без запаздывающей новой строки

Следующий код обрабатывает имена файлов, которые содержат встроенные новые строки, я поместил сценарий полной версии на paste.ubuntu. Это проверяет на существование и соответствие размерам... Код для генерации данных тестирования также включен там.

# This lists the original fully-qualified filename, 
# and its would-be counterpart (assuming it exists) 
unset a i
while IFS= read -r -d $'\0' relf; do
    printf "%s\n$s" "$PWD${relf:1}" "$(dirname "$(dirname "$PWD")")${relf:1}"
done < <(find  . -type f  \! -name '.' -name '*' -print0)

Вот демонстрационный вывод (упомянутой выше) полной версии, где один файл отсутствует, и у другого есть другой размер файла к оригиналу

WARNING -----
NOT in target   ./file1
ok --------
sizes match     ./c/file4-in-subdir
WARNING ------
size mis-match  ./file3   is   triple-spaced
ok --------
sizes match     ./file2
has newline!

8
03.03.2012, 03:05
6 ответов

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

x=$(awk '/some-pattern/ { sub(/\r$/, "") ; printf("%s", $NF) ; exit }' some-file)

Замена избегает Вашей проблемы с окончаниями строки CRLF.

sub(/\r$/, "") удаляет запаздывание CR, если это существует. Как awk обработки \n как запись (строка) разделитель, Вы не должны разделять его, поскольку это не находится в данных, посмотревших на.

printf("%s", $NF) печатает заключительное поле ($NF) без запаздывающей новой строки (print и некоторый другой awk функции добавляют новую строку по умолчанию).

exit происходит после первых двух действий - это - эквивалент m1 в Вашем grep командная строка. Это гарантирует это awk выходы после выполнения предыдущих двух команд - и начиная с этих команд выпущены на соответствие, и awk оценивает данные способом FIFO, это только распечатает первое соответствие.

4
27.01.2020, 20:10
  • 1
    Спасибо, это выглядит изящным, но к сожалению CRLF все еще внутри X –  zetah 03.03.2012, 03:23
  • 2
    :) теперь, это не выглядит изящным больше и это все еще бесполезно –  zetah 03.03.2012, 03:26
  • 3
    @zetah - Не будет a CR, но будет LF. Мне было нелегко понимать то, что Вы хотите от вопроса, надо надеяться, мое редактирование делает то, что Вы хотите. –  Chris Down 03.03.2012, 03:27
  • 4
    OK, на этот раз это делает это хороший - производят последнее слово в строке, если та строка удовлетворяет, некоторое условие шаблона - не знают, возможно, это ясно мне, потому что у меня есть эта проблема, и затем трудно объяснить как неносителя английского языка. Во всяком случае я буду ожидать немного больше, если кто-то обратится к этому с grep/sed решение вместо этого awk (который я не понимаю), и если не я буду использовать его. Спасибо –  zetah 03.03.2012, 03:40
  • 5
    @zetah - я добавлю объяснение, таким образом, можно будет понять это лучше, одна секунда. –  Chris Down 03.03.2012, 03:41

`` или $() удалит новую строку из конца, но сделать это программно, использовать tr.

grep -m1 'some-pattern' some-file | sed -n 's/.* //p' | tr -d '\012\015'

Это удалит возврат каретки и/или новую строку от строки.

То, что могло бы быть проблемой, - то, как Вы затем производите результат. Например, по умолчанию, echo добавляет новая строка. Можно хотеть использовать echo -n или printf.

7
27.01.2020, 20:10
  • 1
    Это также удалит возвраты каретки, которые могут произойти всюду по строке, которая не могла бы быть желаема. –  Chris Down 03.03.2012, 04:07
  • 2
    Да, в то время как возможно встроить возврат каретки в одной строке, это чрезвычайно редко. -m1 гарантирует, что существует только один вывод строки, который, по всей вероятности, имел бы возвратом каретки в конце. –  Arcege 03.03.2012, 04:23
  • 3
    ах tr... интересный, работы и на LF и на файлах CRLF. Я думал бы \010\013 по некоторым причинам, и также \f\r работы правильно. О результате: Я на самом деле не помещаю вывод в переменную, но как переменная, включенная в $() в шаблоне для grep соответствие - some pipe | grep -o " $(...) ". Спасибо за –  zetah 03.03.2012, 04:37

Я предпочитаю этот путь

grep -m1 'some-pattern' some-file | sed -n 's/.* //p' | tr -d '\n'
3
27.01.2020, 20:10

Это работает на меня:

grep -m1 'some-pattern' some-file | sed -n 's/.* //p' | tr -d "\n" | tr -d "\r"
2
27.01.2020, 20:10

Почему не просто позволенный sed сделайте [\r\f] очистка:

# using Bash's $'string' idiom (that decodes ANSI C escape sequences)
# cf. http://wiki.bash-hackers.org/syntax/quoting#ansi_c_like_strings
- X="$(grep -m1 'some-pattern' some-file | sed -n 's/.* //p')"
+ X="$(grep -m1 'some-pattern' some-file | sed -n -e $'s/[\r\f]*$//' -e 's/.* //p')"

Ваш второй подход испытывает недостаток в финале regex для ловли запаздывания CR, \r.

# sample code to remove trailing \r with sed
# cf. http://en.wikipedia.org/wiki/Regular_expression#POSIX_character_classes
printf 'a b c\r' | sed -n 's/^.* \([[:alpha:]]\{1,\}\)/\1/p' | od -c
printf 'a b c\r' | sed -n 's/^.* \([[:alpha:]]\{1,\}\)[[:space:]]*/\1/p' | od -c

# keeps trailing space after c
printf 'a b c \r' | sed -n 's/^.* \([[:alpha:] ]\{1,\}\)[[:space:]]*/\1/p' | od -b
0
27.01.2020, 20:10

Обычная версия GREP (включая GREP -P) всегда выводит канал канала с его совпадением, поэтому, если у вас есть только один результат (или вы только хотите, чтобы окончательная добавленная линия добавлена ), достаточно просто удалить конечный характер выхода, который вы можете сделать по трубе через головы -C-1 .

0
27.01.2020, 20:10

Теги

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