Вы также можете написать правило udev специально для этого устройства.
nano /etc/udev/rules.d/NN -Ваш _набор _из _rules.rules
# My Device which should not have admin rights
ATTRS{idVendor}=="1234", ATTRS{idProduct}=="0042", MODE="664", GROUP="plugdev"
Устройство с vid/pid :1234/0042 по-прежнему будет принадлежать пользователю root, но будет отнесено к группе «plugdev». Если ваш пользователь является членом этой группы, у вас будут права доступа к ней. Вы можете выбрать любую другую группу по вашему желанию.Режим — это двоичный код разрешений устройства. Владелец и группа могут записывать и читать, другие могут только читать устройство.
После этого вы можете запустить lsusb -v
для получения iSerial.
Следующий perl-скрипт пытается сопоставить gene
, product
и sprot
в каждой строке ввода в указанном порядке (, т. е. отдает предпочтение гену над продуктом и продукту над побегом ). Если один из них совпадает, он извлекает слово после совпадения. Предполагается, что слово заключено в двойные -кавычки.
Если совпадение найдено, слово после gene_id
заменяется извлеченным словом.
Строка печатается независимо от того, была она изменена или нет.
#!/usr/bin/perl
while (<>) {
my $word = '';
if (m/\b(?:gene)\s+("[^"]*")/) {
$word = $1;
} elsif (m/\b(?:product)\s+("[^"]*")/) {
$word = $1;
} elsif (m/\b(?:sprot)\s+("[^"]*")/) {
$word = $1;
};
if ($word) {
s/\bgene_id\s+(?:"[^"]*")/gene_id $word/
};
print;
}
В качестве альтернативы это можно было бы написать так, чтобы использовать цикл для перебора ключевых слов соответствия:
#!/usr/bin/perl
while (<>) {
my $word = '';
foreach my $match (qw(gene product sprot)) {
if (m/\b(?:$match)\s+("[^"]*")/) {
$word = $1;
last; # first match wins, exit this loop
}
};
if ($word) {
s/\bgene_id\s+(?:"[^"]*")/gene_id $word/
};
print;
}
ИМО, эта версия лучше, потому что ее легче читать и понимать (, в частности, цикл foreach
подчеркивает, что речь идет об итерации по списку слов ). Что еще более важно, это позволяет избежать повторения оператора $word = $1
-, вы с меньшей вероятностью совершите ошибку, если вам нужно изменить его или добавить дополнительный код, если вам нужно сделать это только один раз, а не три раза. «Не повторяйся» не так важно в такой тривиальной маленькой программе, как эта, но может быть очень важно в больших программах. Во всяком случае, избегать/сводить к минимуму повторения — хорошая привычка программирования.
Если порядок сопоставления не был значимым (, т.е.если вам все равно, какой из них был найден, если он был ), вы можете упростить сценарий:
#!/usr/bin/perl
while (<>) {
my ($word) = m/\b(?:gene|product|sprot)\s+("[^"]*")/;
if ($word) {
s/\bgene_id\s+(?:"[^"]*")/gene_id $word/
};
print;
}
Независимо от того, какую версию скрипта вы используете, сохраните ее, например, как. replace.pl
и сделайте его исполняемым с помощью chmod +x replace.pl
. Или попробуйте их все как replace1.pl
, replace2.pl
, replace3.pl
. Затем запустите его следующим образом:
$./replace.pl input.txt
chrM Gnomon CDS 8345 8513 . + 1 gene_id "semaphorin-3F"; transcript_id "cds-XP_008824843.3"; Parent "rna-XM_008826621.3"; Dbxref "GeneID:103728653_Genbank:XP_008824843.3"; Name "XP_008824843.3"; end_range "8513,."; gbkey "CDS"; gene "semaphorin-3F"; partial "true"; product "semaphorin-3F"; protein_id "XP_008824843.3"; sprot "sp|Q13275|SEM3F_HUMAN";
chrM StringTie exon 2754 3700 . + . gene_id "ND1"; transcript_id "cds-YP_007626758.1"; Parent "gene-ND1"; Dbxref "Genbank:YP_007626758.1,Gene "ID:15088436"; Name "YP_007626758.1"; Note "TAAstopcodoniscompletedbytheadditionof3'AresiduestothemRNA"; gbkey "CDS"; gene "ND1"; product "NADHdehydrogenasesubunit1"; protein_id "YP_007626758.1"; transl_except "(pos:3700..3700%2Caa:TERM)"; transl_table "2";
Чтобы завершить решение perl
, вот как это можно сделать с sed
. Я не уверен, как вы ожидаете, что ваш данный синтаксис будет работать, но на самом деле вам нужно регулярное выражение для соответствия строке
... gene_id "remove me"... some other stuff gene "replacement"... more stuff
======= ====
gene_id "[^"]*" .* gene "[^"]*"
gene_id
и gene
совпадают сами по себе. Строка в двойных кавычках представляет собой конкатенацию двойной кавычки, любого количества символов, не являющихся двойными кавычками ([^"]*
), и еще одной двойной кавычки. Наконец-то у вас есть нечто среднее.*
Теперь вам нужно разместить \(\)
вокруг деталей, которые необходимо переработать при замене:
sed 's/gene_id "[^"]*"\(.* gene \("[^"]*"\)\)/gene_id \2\1/'
Внешняя пара закрывает все, что следует оставить нетронутым. Это повторно используется как \1
в замене. Внутренняя пара — это строка, которую вы хотите повторно использовать как gene_id
.
Теперь, если вы хотите иметь product
или sprot
в качестве альтернативных замен, вы можете использовать альтернативные строки расширенных регулярных выражений:
sed -E 's/gene_id "[^"]*"(.*(gene|product|sprot) ("[^"]*"))/gene_id \3\1/'
, но это не будет предпочтительнее gene
над product
над sprot
, а предпочтет последнее из присутствующих. Если вы хотите иметь такой порядок предпочтения, вам нужны отдельные шаги и начните с последнего, чтобы его можно было заменить лучшим:
sed 's/gene_id "[^"]*"\(.* sprot \("[^"]*"\)\)/gene_id \2\1/
s/gene_id "[^"]*"\(.* product \("[^"]*"\)\)/gene_id \2\1/
s/gene_id "[^"]*"\(.* gene \("[^"]*"\)\)/gene_id \2\1/'
Или, если приказ gene
,Известно, что product
и sprot `фиксированы, вы можете сначала извлечь предпочтительный идентификатор, пока фактическая строка остается в пространстве удержания:
sed -E 'h;s/(sprot|product|gene) ("[^"]*").*/#\2/;s/.*#//;G;s/(.*)\n(.*gene_id )"[^"]*"/\2\1/'
Маркером #
может быть любая строка, которая, как известно, не является частью идентификатора; для GNU sed
вы можете использовать \n
, чтобы быть уверенным. Таким образом, вы заменяете первую из указанных строк маркером и удаляете остальную часть строки, затем удаляете все до маркера, так что теперь в пространстве шаблона остается только идентификатор. Затем с помощью G
будет добавлена исходная строка (, которую мы сохранили в буфере удержания с помощью h
), а затем идентификатор (части перед новой строкой )заменит "string"
после gene_id
. ]. Как-то проще написать, чем объяснить.
Мы используем свойство хэша, заключающееся в том, что если к заданному ключу применяется несколько значений, то последнее становится окончательным значением.
perl -lpe 'my($l,%h)=($_);
$h{gene_id}=$_ for map {
$l =~ /\b$_\s+(".*?");/
} reverse qw(gene product sprot);
s/\bgene_id\s+\K".*?";/$h{gene_id};/;
' your_file_genes
Поскольку все команды одинаковы, а меняются только имена, мы можем легко сделать управляемой всю операционную таблицу, в которой мы просто задаем имена полей, а цикл for позаботится обо всем остальном.
for i in gene product sprot;do
cat - <<\_FMT_ |\
sed -e "s/%s/$i/"
s/(\<gene_id\s+)"[^"]*"(.*\s%s\s+("[^"]*"))/\1\3\2/;t
_FMT_
done | sed -Ef - your_file_genes