Команде r
может предшествовать ноль или один адрес.
Из документации sed
:
Sed Addresses
Адрес не требуется, но если указан, должен быть числом (которое подсчитывает входные строки в совокупности во входных файлах), символом доллара (
'), который относится к последней строке ввода, или адресом контекста (который состоит из регулярного выражения, перед которым следует разделитель, а за которым следует разделитель). [ 1127] blockquote>
), который относится к последней строке ввода, или адресом контекста (который состоит из регулярного выражения, перед которым следует разделитель, а за которым следует разделитель). [ 1127] blockquote>В ваших примерах не используется число или
$
в качестве спецификатора адреса. Единственная оставшаяся опция - это регулярное выражение, заключенное в разделители. Разделителем по умолчанию дляregex
вsed
является косая черта (/
).Поскольку
/
является разделителемregex
, любое использование/
внутриregex
необходимо избегать (т. Е. Ему предшествует\
).
Команда, которая вам нужна:sed -i '/\/def\/ghi\/jkl/ r numbers' letters2
Чтобы использовать другой разделитель для регулярного выражения (чтобы избежать необходимости избегать прямой косой черты), вы должны ставить перед ним обратную косую черту, когда он используется в качестве открытого разделителя. (до адреса). Не избегайте его, когда он используется после
regex
. Выход из него внутриregex
говоритsed
использовать его буквальное значение.Команда в этом случае:
sed -i '\@/def/ghi/jkl@ r numbers' letters2
Пример, который вы утверждаете, работает (
sed -i "def r numbers" letters
), не следует этому шаблону и фактически не работает (по крайней мере, на macOSsed
я использую).
Это должно бытьsed -i "/def/ r numbers" letters
или, если быть более точным,sed -i "/^def$/ r numbers" letters
.В ваших примерах не используется число или
$
в качестве спецификатора адреса. Единственная оставшаяся опция - это регулярное выражение, заключенное в разделители. Разделителем по умолчанию дляregex
вsed
является косая черта (/
).Поскольку
[110]/
является разделителемregex
, любое использование/
внутриregex
необходимо избегать (т. Е. Ему предшествует\
).
Команда, которая вам нужна:Чтобы использовать другой разделитель для регулярного выражения (чтобы избежать необходимости избегать прямой косой черты), вы должны ставить перед ним обратную косую черту, когда он используется в качестве открытого разделителя. (до адреса). Не избегайте его, когда он используется после
regex
. Выход из него внутриregex
говоритsed
использовать его буквальное значение.Команда в этом случае:
[111]Пример, который вы утверждаете, работает (
sed -i "def r numbers" letters
), не следует этому шаблону и фактически не работает (по крайней мере, на macOSsed
я использую).
Это должно бытьsed -i "/def/ r numbers" letters
или, если быть более точным,sed -i "/^def$/ r numbers" letters
.
To prevent an exception in a handler from propagating to the event generator, the answer is to manually invoke each item in the MultiCast Delegate (i.e. the event handler) inside of a try-catch
All handlers will get called, and the exception won't propagate.
public EventHandler<EventArgs> SomeEvent;
protected void OnSomeEvent(EventArgs args)
{
var handler = SomeEvent;
if (handler != null)
{
foreach (EventHandler<EventArgs> item in handler.GetInvocationList())
{
try
{
item(this, args);
}
catch (Exception e)
{
// handle / report / ignore exception
}
}
}
}
What remains is for you to implement the logic for what do do when one or more event recipients throws and the others don't. The catch() could catch a specific exception as well and roll back any changes if that is what makes sense, allowing the event recipient to signal the event source that an exceptional situation has occurred.
As others point out, using exceptions as control flow isn't recommended. If it's truly an exceptional circumstance, then by all means use an exception. If you're getting a lot of exceptions you probably want to use something else.
Общий шаблон, который вы увидите для фреймворков:
public class Example
{
public int Counter { get; private set; }
public void IncreaseCounter()
{
OnCounterChanging(EventArgs.Empty);
this.Counter = this.Counter + 1;
OnCounterChanged(EventArgs.Empty);
}
protected virtual void OnCounterChanged(EventArgs args)
{
if (CounterChanged != null)
CounterChanged(this, args);
}
protected virtual void OnCounterChanging(EventArgs args)
{
if (CounterChanging != null)
CounterChanging(this, args);
}
public event EventHandler<EventArgs> CounterChanging;
public event EventHandler<EventArgs> CounterChanged;
}
Если пользователь хочет создать исключение, чтобы предотвратить изменение значения, он должен сделать это в OnCounterChanging () событие вместо OnCounterChanged (). По определению имени (прошедшее время, суффикс -ed), которое подразумевает, что значение было изменено.
Редактировать:
Обратите внимание, что обычно вы хотите держаться подальше от большого количества дополнительных блоков try..catch / finally. поскольку обработчики исключений (включая try..finally) дороги в зависимости от языковой реализации. т.е. у модели с фреймами стека win32 или модели исключений с отображением ПК есть свои плюсы и минусы, однако, если этих фреймов будет слишком много, они оба будут дорогостоящими (либо по пространству, либо по скорости выполнения). Еще одна вещь, о которой нужно помнить при создании фреймворка.
В этом случае, я думаю, вам следует воспользоваться репликой от Workflow Foundation. В методе OnCounterChanged окружите вызов делегата общим блоком try-catch. В обработчике catch вам нужно будет сделать то, что по сути является компенсирующим действием - откат счетчика.
Well, you could compensate if it was critical:
public void IncreaseCounter()
{
int oldCounter = this.Counter;
try {
this.Counter = this.Counter + 1;
OnCounterChanged(EventArgs.Empty);
} catch {
this.Counter = oldCounter;
throw;
}
}
Obviously this would be better if you can talk to the field (since assigning a field won't error). You could also wrap this up in bolierplate:
void SetField<T>(ref T field, T value, EventHandler handler) {
T oldValue = field;
try {
field = value;
if(handler != null) handler(this, EventArgs.Empty);
} catch {
field = oldField;
throw;
}
}
and call:
SetField(ref counter, counter + 1, CounterChanged);
or something similar...
Will not simply swapping the order of the two lines in IncreaseCounter
enforcestrong exception safety for you?
Or if you need to increment Counter
before you raise the event:
public void IncreaseCounter()
{
this.Counter += 1;
try
{
OnCounterChanged(EventArgs.Empty);
}
catch
{
this.Counter -= 1;
throw;
}
}
In a situation where you have more complex state changes (side effects) going on, then it becomes rather more complicated (you might have to clone certain objects for example), but in for this example it would seem quite easy.