http://ubuntuforums.org/showthread.php?t=2316240
Ответ здесь. Проблема в том, что каким-то образом определяется общий тачпад, хотя на самом деле используется другой тачпад. Все команды, которые я пробовал, шли к общему тачпаду, которого на самом деле не существует, поэтому ничего не сработало.
Попробовал исправление, и теперь все в порядке.
Мы можем выполнить проверку, используя sed
, хотя приведенный ниже код написан для GNU sed
, где мы сохраняем последний полный диапазон /pat2/../pat1/
в пространстве хранения. И затем мы поддерживаем оболочку расширяющейся границы, начиная с линии рядом с последней строкой диапазона, сохраненного в удержании, и продвигаясь к eof.
sed -e '
/pattern2/,/pattern1/!b
H;/pattern2/h;/pattern1/!{$!d;g;q;}
${g;bc;}
N;s/.*\n//
:a
$bd;N
/pattern2/!ba
:b
$bd;N
/pattern2.*\n.*pattern1/!bb
x;$!{n;/pattern2/bb;ba;}
G
:c;s/\(.*\)\n.*/\1/;q
:d;x;s/\(.*\)\n.*/\1/;G
' input,txt
В этом методе мы помещаем весь файл в пространство шаблонов, затем, используя мощь регулярных выражений, находим и определяем последнюю строку /pattern1/ в диапазоне и удаляем ее.
sed -Ee '
$!{N;H;s/.*//;x;D;}
/pattern2/!q;/pattern1/!q;/pattern2.*\n.*pattern1/!q
h;s/((.*\n)?[^\n]*pattern2[^\n]*)\n(.*pattern1.*)/\3/
s/^//;tdummy
:dummy
s/\n[^\n]*pattern1[^\n]*\n/\n/;ta
s/^[^\n]*pattern1[^\n]*\n//;ta
s/\n[^\n]*pattern1[^\n]*$//;ta
s/^[^\n]*pattern1[^\n]*$//
:a;x;s/((.*\n)?[^\n]*pattern2[^\n]*)\n.*pattern1.*/\1/;G
' input.file
Чтобы найти номер строки этой строки:
lineno=$( nl file | tac | awk '/pattern1/ {last = $1} /pattern2/ {print last; exit}' )
Использование nl
для добавления номеров строк в файл, tac
чтобы поменять местами линии,
и awk
для печати номера строки для последнего "шаблона1" перед и первого "шаблона2".
А затем удалить эту строку:
sed -i "${lineno}d" file
У меня нет компьютера для тестирования, но это должно работать с gnused
:
sed 'H;1h;$!d;g;s/.*pattern1/@@@/;s/\n[^\n]*pattern2[^\n]*//;H;g;s/\(.*pattern1\).*@@@/\1/'
Вместо @@@
используйте любую последовательность символов, о которой известно, что она не является частью файла.
Это ex
один -вкладыш.(ex
является предшественником и скриптовой формой vi
.)
printf '%s\n' '$?pattern2?/pattern1/d' x | ex file.txt
Сохранение x
и выход. Измените его на %p
, если вы хотите просто распечатать измененный файл, но не сохранить изменения (хорошо для тестирования ).
$
означает последнюю строку файла; ?pattern2?
— адрес, означающий первый результат поиска pattern2
в обратном направлении, начиная с текущей позиции; /pattern1/
— адрес прямого -поиска, а d
— команда удаления строки.
Используйте ex
, когда вам нужна прямая и обратная адресация.
То же самое можно сделать интерактивно в vi
или Vim:
vim file.txt
Затем введите
:$?pattern2?/pattern1/d
и нажмите Enter.
Затем сохраните и выйдите, нажав :x
Enter.
n=$(sed -ne '/pattern2/,/pattern1/{/pattern1/=;}' yourfile | tail -n 1)
sed -i'' -e "${n}d" yourfile
# invoke GNU sed with extended RE(-E), slurp mode(-z), in-place editing(-i) options
sed -i -Eze '
h;s/(.*pattern2[^\n]*)\n.*/\1/p; # traverse till the last pat2 line and print it
g;s/.*pattern2[^\n]*(\n.*)/\1/; # remove till the last pat2 line
s/\n[^\n]*pattern1[^\n]*//; # now look for the 1st occurrence of pat1
; # clip that line, & print what remains
' inp
Рабочий:
/pattern2/,/pattern1/
для того, чтобы он учитывался. |----A---| |----B----|--------C--------|D|----------E---------|-F-|
perl -0777pi -e 's/.*pattern2(?:(?!pattern1).)*\K(?-s:\n.*pattern1.*$)//ms' yourfile
A
:Вызов Perl
в режиме slurp
(-0777
)+ line-by-line
чтение -в +autoprint
(-p
)включено, in-place
редактирование(-i
)B+C
:Перейдите к последнему вхождению шаблона2, затем замедлите движение и двигайтесь устойчиво, очищая не шаблон1 D
:Когда вы доберетесь сюда, это будет последний пит-стоп, где шаблон 1 не был замечен после последнего шаблона 2, отметьте его \K
. это означает, что это не появится в потребляемой части ввода, а только в согласованной части.E
:Этим мы отключаем модификатор соответствия шаблона /s
cloistered, что означает, что в этой части совпадения .
больше не соответствует новой строке, что означает, что мы не можем переходить дальше строк. Мы просто сопоставляем всю единственную строку с шаблоном1 и удаляем это. То, что остается в пространстве шаблона, печатается автоматически. -F
:Мы вызываем s///
с модификаторами /s
и /m
. Мы выборочно отключим модификатор /s
внутри регулярного выражения, чтобы адаптировать его к нашим потребностям. Если вы хотите сделать только один проход в файле и свести к минимуму количество строк, хранящихся в памяти, вы можете использовать awk
с подходом конечного автомата.Это не самые короткие решения, но их легко придумать и читать/обслуживать. Вы можете заменить имена состояний числами, чтобы сделать его (возможно )более эффективным.
PATTERN1=pattern1 PATTERN2=pattern2 awk '
BEGIN {
p1 = ENVIRON["PATTERN1"]
p2 = ENVIRON["PATTERN2"]
state = "init"
}
state == "init" {
if ($0 ~ p2) state = "p2_found"
print
next
}
state == "p2_found" {
if ($0 ~ p1) {
state = "p1_found"
p1_line = $0
printf "%s", hold
hold = ""
} else if ($0 ~ p2) {
# we can print the text held since the last p2
printf "%s", hold
hold = $0 RS
} else hold = hold $0 RS
next
}
state == "p1_found" {
if ($0 ~ p2) {
state = "p2_found"
# the line that matched p1 is not discarded
printf "%s\n%s", p1_line, hold;
hold = ""
}
hold = hold $0 RS
}
END {
# here we are not printing p1_line which is how it is discarded
printf "%s", hold
}'
(Я предполагаю, что нет строк, соответствующих как pattern1
, так иpattern2
).