Параметр --list-only
не определяет файлы, которые будут переданы; он идентифицирует только те файлы, которые являются кандидатами на передачу. Вы можете увидеть это здесь
touch aa bb cc; ln -s cc dd
rsync --list-only --no-links -a ?? /tmp
rsync -av ?? /tmp
rsync --list-only --no-links -a ?? /tmp
Вывод из последнегоrsync
-rw-r--r-- 0 2018/09/05 16:35:01 aa
-rw-r--r-- 0 2018/09/05 16:35:01 bb
-rw-r--r-- 0 2018/09/05 16:35:01 cc
lrwxrwxrwx 2 2018/09/05 16:35:01 dd -> cc
Рассмотрим последний rsync
, где файлы уже перенесены и остаются без изменений на исходнике. Если бы --list-only
показывал файлы, которые необходимо передать, в списке ничего не было бы. Однако он по-прежнему показывает набор исходных файлов, которые необходимо учитывать.
Если вы хотите использовать контекст цели для управления набором файлов, о которых необходимо сообщить, используйте--dry-run --info=name
rsync --dry-run --info=name --archive --no-links ?? /tmp
Или, если вы хотите, чтобы вывод был аналогичен тому, что получается при --list-only
(, особенно при исключении типа записи из первого символа)
rsync --dry-run --info=name --out-format='%B%16l %t %f' --archive --no-links ?? /tmp
Начальный вывод
skipping non-regular file "dd"
rw-r--r-- 0 2018/09/05 16:42:30 aa
rw-r--r-- 0 2018/09/05 16:42:30 bb
rw-r--r-- 0 2018/09/05 16:42:30 cc
Последующий вывод после копирования файлов
skipping non-regular file "dd"
Для начала вот как получить числовое значение:
$ echo 'foo = 1700;' | sed -n -e 's/^foo = \([0-9]\+\).*/\1/p'
1700
Это использует базовые регулярные выражения sed
по умолчанию (BRE ). Вы также можете использовать расширенные регулярные выражения (ERE )с параметром sed -E
:
echo 'foo = 1700;' | sed -n -E -e 's/^foo = ([0-9]+).*/\1/p'
1700
Вложенное выражение -[0-9]+
внутри круглых скобок (
... )
захватывает еще одну -или -цифру. Это называется «группой захвата» и используется при замене на \1
(, которая является первой группой захвата -, если имеется несколько групп захвата, их можно использовать как \1, \ 2, \3 и т. д. ).
В этом случае сценарий sed пытается заменить всю строку только группой захвата \1 и, если это удалось, вывести измененную строку.
Затем вы хотите преобразовать вывод sed
в переменную. Вы делаете это с помощью подстановки команды . например.
$ myvar=$(echo 'foo = 1700;' | sed -n -E -e 's/^foo = ([0-9]+).*/\1/p')
$ echo $myvar
1700
Чтобы использовать это в своем скрипте, просто используйте свой файл в качестве аргумента для sed вместо того, чтобы передавать в него echo...
.
myvar=$(sed -n -E -e 's/^foo = ([0-9]+).*/\1/p' file)
Чтобы обрезать пробелы или справиться со строками, которые могут иметь необязательные начальные пробелы или необязательные пробелы вокруг =
и т. д.:
myvar=$(sed -n -E -e 's/^[[:space:]]*foo[[:space:]]*=[[:space:]]*([0-9]+).*/\1/p' file)
Обратите внимание, что некоторые версии sed (GNU sed, по крайней мере. возможно, другие )понимают perl's
\s
, так что вы можете сократить это до:
myvar=$(sed -n -E -e 's/^\s*foo\s*=\s*([0-9]+).*/\1/p' file)
Использованиеgawk
:
Предполагается, что файл input
является:
$ cat input
foo = 1700
foo=17
foo 2000
foobarfoo = 200
foo = foo = 14 243
foo =
200 = foo
Эта gawk
команда выполнит:
awk '{if(match($0, /\<foo\s*=\s*[0-9]+/)){
a=substr($0,RSTART,RLENGTH);sub(/foo\s*=\s*/, "",a); print a}}' input
Или с помощью этой gawk
команды:
awk '{if(match($0, /\<foo\s*=\s*[0-9]/))
{ l=RLENGTH-1;match($0, /foo\s*=\s*[0-9]+/)
print substr($0,RSTART+l,RLENGTH-l); }}' input
Если шаблон простой, как в foo = 1700
, то есть пробел после foo и знак равенства, то указанную выше команду можно сократить:
awk '{if(match($0, /\<foo = [0-9]+/)) print substr($0,RSTART+6,RLENGTH-6);}' input
Другой метод:
awk '/\<foo\s*=\s*[0-9]+/ {print gensub(/(.*)(foo\s*=\s*)([0-9]+)(.*)/, "\\3", "g") }' input
В этой команде все захваченные группы заменяются третьей захваченной группой с использованием обратной ссылки(\\3
). gensub()
— встроенная функция gawk
.
Для полноты картины, с grep
реализациями, которые поддерживают -o
иperl
-подобно регулярным выражениям с -P
, вы можете сделать:
grep -Po 'foo\s*=\s*\K\d+'
Где:
\s
соответствует любому символу пробела *
0 или более предшествующих атомов. Например, \s*
соответствует 0 или более пробельным символам. \d
соответствует десятичной цифре (, обычно такой же, как [0123456789]
, но не [0-9]
, которая часто соответствует гораздо большему количеству символов ). +
соответствует одному или нескольким предшествующим атомам. \K
сбрасывает начало согласованной части (what на K
eep или, в случае grep -o
what на o
вывод ). Таким образом, будут напечатаны все последовательности из одной или нескольких цифр, которые следуют за foo=
, с любым количеством пробелов, допустимых по обе стороны от =
, даже если в данной строке встречается более одной цифры.
С помощью pcregrep
вы также можете указать число после -o
, чтобы напечатать то, что совпадает с группой захвата, а не всю совпадающую часть:
pcregrep -o1 'foo\s*=\s*(\d+)'
Переносимо, вы можете использовать настоящую вещь:perl
:
perl -lne 'print $1 for m{foo\s*=\s*(\d+)}g'
awk '{for(i=1;i<=NF;i++){if($i ~ /foo/ && $0 ~ /foo.*=.*[0-9]*/){gsub(";","",$(i+2));print $(i+2)}}}' filename
Проверено, работает нормально
Предположим, вы хотите выбрать числовое foo
значение,
echo 'foo = 1700;' | awk '$1=="foo" {print $NF+0}'
1700
По умолчанию awk
разбивается на пробел (, а не на один пробел ). NF
— количество полей, в данном случае 3; $NF
— строковое значение третьего поля с пробелами. +0
преобразует эту строку 1700;
в числовое значение 1700
.
Он будет работать с такими строками, как foo = 1700;
, но не будет работать со строками, такими как foo=1700;
. Из вашего вопроса я не был уверен, были ли вы просто обеспокоены удалением лишних пробелов или что в ваших данных может не быть пробелов и всего остального, а =
и ;
являются единственными граничными точками. Если вы хотите игнорировать любые пробелы, независимо от того, есть они или нет, вам лучше использовать sed
,
echo 'foo=1700;' | sed -n 's/^foo *= *//p' | sed -e 's/;$//' -e 's/ *$//'
1700