Это может быть не так, как правило, как то, что вы действительно хотите, но вот отправную точку:
sed -n '/SOMETHING/!q;p'
Это говорит: проверьте на наличие совпадения / что-то /
.
Если линия не совпадает (используя !
, чтобы инвертировать результат теста), затем выйти.
В противном случае распечатайте эту строку и продолжайте до следующей строки.
Это не сразу же гибко, чтобы позволить вам делать то, что вы просили,
А также другие манипуляции на файл, все в одном COD
команда.
awk
имеет два режима призыва, один с текстом программы в командной строке и другой с программой из файла. Это указано в синопсе страницы человека AWK (этот из Mawk на Ubuntu 12.04):
mawk [-W option] [-F value] [-v var=value] [--] 'program text' [file
...]
mawk [-W option] [-F value] [-v var=value] [-f program-file] [--]
[file ...]
должен вызывать ли первую форму программу или не зависит от определения программы, которую вы хотите использовать. Я бы сказал, обе формы включают в себя программы, в зависимости от первой программы указана как аргумент командной линии. Оба ваших примера должны быть первой формы, так как не включает в себя опцию -F
. То, что второй пример имеет многослойный аргумент командной линии, по отношению к этому неактуально.
Это не уникально для awk
. например Python по умолчанию интерпретает аргумент командной линии в качестве имени программы, но с опцией
позволяет указывать программу в командной линии (т. Е. По умолчанию находятся наоборот вокруг awk
).
Независимо от этого, это связь с использованием труб. Это позаботится о синтаксисе оболочки и ОС, единственное, что ваш скрипт должен делать, это запись на STDOUT, REPS. Читайте из Stdin. Так что да AWK
программы могут общаться по трубам.
lcomma() { sed '
$x;$G;/\(.*\),/!H;//!{$!d
}; $!x;$s//\1/;s/^\n//'
}
Это должно удалять только последнее вхождение ,
в любом входном файле - и оно по-прежнему будет печатать те, в которых ,
не происходит. В основном он буферизирует последовательности строк, которые не содержат запятую.
Когда он встречает запятую, он заменяет текущий буфер строки буфером удержания и в этом пути одновременно распечатывает все строки, возникшие с момента последней запятой , и освобождает его буфер удержания.
Я просто копал свой файл истории и нашел следующее:
lmatch(){ set "USAGE:\
lmatch /BRE [-(((s|-sub) BRE)|(r|-ref)) REPL [-(f|-flag) FLAG]*]*
" "${1%"${1#?}"}" "$@"
eval "${ZSH_VERSION:+emulate sh}"; eval '
sed " 1x; \\$3$2!{1!H;\$!d
}; \\$3$2{x;1!p;\$!d;x
}; \\$3$2!x;\\$3$2!b'"
$( unset h;i=3 p=:-:shfr e='\033[' m=$(($#+1)) f=OPTERR
[ -t 2 ] && f=$e\2K$e'1;41;17m}\r${h-'$f$e\0m
f='\${$m?"\"${h-'$f':\t\${$i$e\n}\$1\""}\\c' e=} _o=
o(){ IFS=\ ;getopts $p a "$1" &&
[ -n "${a#[?:]}" ] &&
o=${a#-}${OPTARG-${1#-?}} ||
! eval "o=$f;o=\${o%%*\{$m\}*}"
}; a(){ case ${a#[!-]}$o in (?|-*) a=;;esac; o=
set $* "${3-$2$}{$((i+=!${#a}))${a:+#-?}}"\
${3+$2 "{$((i+=1))$e"} $2
IFS=$; _o=${_o%"${3+$_o} "*}$*\
}; while eval "o \"\${$((i+=(OPTIND=1)))}\""
do case ${o#[!$a]} in
(s*|ub) a s 2 '' ;;
(r*|ef) a s 2 ;;
(f*|lag) a ;;
(h*|elp) h= o; break ;;
esac; done; set -f; printf "\t%b\n\t" $o $_o
)\"";}
Это на самом деле довольно хорошо. Да, он использует eval
, но никогда не передает ему ничего за пределы числовой ссылки на его аргументы. Он создает произвольные сценарии sed
для обработки последнего совпадения. Я покажу вам:
printf "%d\" %d' %d\" %d'\n" $(seq 5 5 200) |
tee /dev/fd/2 |
lmatch d^.0 \ #all re's delimit w/ d now
-r '&&&&' \ #-r or --ref like: '...s//$ref/...'
--sub \' sq \ #-s or --sub like: '...s/$arg1/$arg2/...'
--flag 4 \ #-f or --flag appended to last -r or -s
-s\" \\dq \ #short opts can be '-s $arg1 $arg2' or '-r$arg1'
-fg #tacked on so: '...s/"/dq/g...'
Это печатает следующее на stderr. Это копия ввода lmatch
:
5" 10' 15" 20'
25" 30' 35" 40'
45" 50' 55" 60'
65" 70' 75" 80'
85" 90' 95" 100'
105" 110' 115" 120'
125" 130' 135" 140'
145" 150' 155" 160'
165" 170' 175" 180'
185" 190' 195" 200'
Функция eval
ed выполняет итерацию через все ее аргументы один раз. По мере перемещения над ними он соответствующим образом итерирует счетчик в зависимости от контекста для каждого переключателя и пропускает множество аргументов для следующей итерации. С этого момента он делает одну из нескольких вещей на аргумент:
$ a
к $ o
. $ a
назначается на основе значения $ i
, которое увеличивается на число arg для каждого обработанного arg. $ a
присваивается одно из двух следующих значений:
a = $ ((i + = 1))
- этот параметр назначается, если либо короткая опция не имеет добавленного аргумента, либо опция была длинной. a = $ i # -?
- этот параметр назначается, если опция является короткой и к ней присоединен арг . a =\$ {$ a} $ {1: + $ d\$ {$ (($1))\}}
- Независимо от первоначального назначения, значение $ a
всегда оборачивается фигурными скобками и - в случае -s
- иногда $ i
увеличивается еще на один и дополнительно ограничивается поле добавляется. В результате eval
никогда не передается последовательности, содержащему неизвестных. На каждый из аргументов командной строки ссылается их числовой номер аргумента - даже разделитель, который извлекается из первого символа первого аргумента и является единственным случаем использования любого символа, который не скрыт. В основном, функция является макрогенератором - она никогда не интерпретирует значения аргументов в каких-либо специальных путях, потому что sed
может (и, конечно) легко обрабатывать это при разборе сценария. Вместо этого он просто разумно упорядочивает свои аргументы в работоспособный сценарий.
Вот некоторые отладочные выходные данные функции в работе:
... sed " 1x;\\$2$1!{1!H;\$!d
}; \\$2$1{x;1!p;\$!d;x
}; \\$2$1!x;\\$2$1!b
s$1$1${4}$1
s$1${6}$1${7}$1${9}
s$1${10#-?}$1${11}$1${12#-?}
"
++ sed ' 1x;\d^.0d!{1!H;$!d
}; \d^.0d{x;1!p;$!d;x
}; \d^.0d!x;\d^.0d!b
sdd&&&&d
sd'\''dsqd4
sd"d\dqdg
'
И поэтому lmatch
можно использовать для простого применения регексов к данным после последнего совпадения в файле. Результат выполнения команды выше:
5" 10' 15" 20'
25" 30' 35" 40'
45" 50' 55" 60'
65" 70' 75" 80'
85" 90' 95" 100'
101010105dq 110' 115dq 120'
125dq 130' 135dq 140sq
145dq 150' 155dq 160'
165dq 170' 175dq 180'
185dq 190' 195dq 200'
..., которая, учитывая подмножество ввода файла, следующего за последним совпадением /^ .0/
, применяет следующие замены:
sdd & & & & & d
-заменяет $ match
на себя 4 раз. sd 'dsqd4
- четвертая единичная цитата, следующая за началом строки с момента последнего матча. sd "d\dqd2
- ditto, но для двойных кавычек и глобально. И поэтому, чтобы продемонстрировать, как можно использовать lmatch
для удаления последней запятой в файле:
printf "%d, %d %d, %d\n" $(seq 5 5 100) |
lmatch '/\(.*\),' -r\\1
5, 10 15, 20
25, 30 35, 40
45, 50 55, 60
65, 70 75, 80
85, 90 95 100
-121--28715- Использование стандартного перенаправления будет работать на стандартном выходе:
$ awk -F'"' -v OFS='' '{ for (i=2; i<=NF; i+=2) gsub(",", "", $i) } 1' infile > test.out
$
Это все равно будет выводить ошибки на экран.
Однако, если вы хотите, чтобы ошибки и стандартные исходили в файл, то запустите:
$ awk -F'"' -v OFS='' '{ for (i=2; i<=NF; i+=2) gsub(",", "", $i) } 1' infile 2>&1 > test.out
$
Или вы можете отделить ошибки от стандартного вывода:
awk -F'"' -v OFS='' '{ for (i=2; i<=NF; i+=2) gsub(",", "", $i) } 1' infile 2> errors.out 1 > test.out
-121--175439- Строго говоря, при вызове awk вы ссылаетесь на интерпретатор, а не на язык. Язык называется AWK .
awk
(или mawk
, nawk
) - это только утилита, которая будет выполнять программы, написанные на языке программирования AWK
.
Как определено POSIX, программа awk является:
программа
Если параметр -f не указан, первым операндом для awk должен быть текст программы awk. Приложение должно предоставить программу операнд как единственный аргумент к неловкости. Если текст не заканчивается на , awk интерпретирует текст так, как если бы он это сделал.
Таким образом, если вы не используете опцию -f
, вы можете рассматривать два примера в качестве программы «неловкости».