Я продолжаю читать sed
документацию и множество постов, но, похоже, не могу разобраться. У меня есть большое количество файлов Java. В этих файлах есть вызовы метода, которые принимают перечисление, преобразованное в целое число с помощью метода toInt()
. Я хочу просмотреть все файлы и избавиться .toInt()
от определенного перечисления.
Вот что мне нужно. Исходные строки кода:
foo(ENUM_NAME.ENUM_VALUE.toInt(), arg2, arg3)
foo(ENUM_NAME.ENUM_VALUE2.toInt(), arg2, arg3)
Я хочу закончить так:
foo(ENUM_NAME.ENUM_VALUE, arg2, arg3)
foo(ENUM_NAME.ENUM_VALUE2, arg2, arg3)
ENUM_VALUE
могут быть сотни различных возможностей, поэтому я не могу жестко кодировать. Кажется, есть некоторая путаница относительно того, что нужно изменить, поэтому я постараюсь быть более ясным.
В моих файлах Java есть перечисление, называемое TRANF_FIELD
. Значения, доступные для этого перечисления, могут быть одним из двух тысяч значений, за которыми следует .toInt()
. Мне нужно избавиться от .toInt()
. Все имена функций не имеют значения.
Ниже приведены примеры конструкций кода, которые встречаются в моем коде Java, и способы их обработки:
TRANF_FIELD.TRANF_VALUE_1.toInt()
Я хочу.toInt()
удалённое, оставивTRANF_FIELD.TRANF_VALUE_1
остаток.
TRANF_FIELD.TRANF_KILL_ME.toInt()
Я хочу.toInt()
удалённое, оставивTRANF_FIELD.TRANF_KILL_ME
TRANG_FIELD.TRANG_VALUE_1.toInt()
Никаких изменений, потому что это неTRANF_FIELD
.
TRANF_FIELD.TRANF_VALUE_1.length()
Никаких изменений, потому что это не.toInt()
.
решение1
Кажется, вы хотите изменить все вхождения
TRANF_FIELD.some_enum_value.toInt()
к
TRANF_FIELD.that_enum_value
оставляя другие перечисления (например, TRANG_FIELD.TRANG_VALUE.toInt()
) и другие методы (например, TRANF_FIELD.TRANF_VALUE.length()
) в покое. Это кажется простым:
sed 's/\(TRANF_FIELD\.[A-Za-z0-9_]*\)\.toInt()/\1/'
где
[A-Za-z0-9_]*
любое количество буквенно-цифровых символов (включая подчеркивания). Это предназначено для сопоставления с любым допустимым значением перечисления. На самом деле,[A-Za-z_][A-Za-z0-9_]*
было бы лучше, поскольку[A-Za-z0-9_]*
могло бы соответствовать пустой строке или строке, начинающейся с цифры.\(
…\)
группирует имя перечисления (TRANF_FIELD
), буквенную точку (\.
) и значение перечисления (из первого маркера).\1
означает «заменить всю найденную вами строку первой группой», т. е. отбросить часть.toInt()
.- Чтобы обработать несколько вхождений в строке, добавьте
g
(global) после последней косой черты. - Это не будет обрабатывать встроенные пробелы, например,
TRANF_FIELD . TRANF_VALUE
. Исправление этого остается в качестве упражнения. Это не будет обрабатывать выражения, разбитые на строки; например,
i = TRANF_FIELD .TRANF_VALUE.toInt();
Это исправить сложнее.
решение2
Спасибо всем за помощь, ребята. Я добавил -i из одного ответа, включая путь ко всем файлам java, к тому, что предложил G-man, и это работает. Если вы когда-нибудь будете на Лонг-Айленде, я угощу вас пивом. Это сэкономило мне кучу времени.
sed -i 's/\(TRANF_FIELD\.[A-Za-z0-9_]*\)\.toInt()/\1/g'
решение3
В зависимости от вашей ОС встроенный оператор ( -i
) sed
может сделать следующее:
sed -i 's:\.toInt()::' filename
Где он просто заменит экземпляр ".toInt()" на "" - символ .
экранирован, чтобы не действовать как подстановочный знак.
Поскольку вы упомянули несколько файлов, вам придется выполнить эту команду циклически, выполнив поиск всех файлов в текущем каталоге и подкаталогах:
find . -type f -exec sed -i 's:\.toInt()::' {} \;
Однако это приведет к ошибке, если имена файлов содержат пробелы, поэтому xargs
для решения этой проблемы мы можем использовать команду, которая заключит все имена файлов в кавычки:
find . -type f | xargs -I{} sed -i 's:\.toInt()::' "{}"
Однако это также выберет и скомпилированные файлы, поэтому, чтобы избежать этого, мы можем использовать полезную функцию, чтобы perl
игнорировать их:
find . -type f | perl -nle 'print if -T' | xargs -I{} sed -i 's:\.toInt()::' "{}"
решение4
sed 's/ENUM_NAME\.\(.*\)\.toInt()/ENUM_NAME.\1/g'