Я согласен с использование find является лучшим вариантом . Но я хочу добавить, почему ваша команда не работает.
Ваша команда:
$ ls process_logs/ | grep -P '^some_pattern_matching_regex_goeshere.txt$' | xargs rm -f
ls
выводит имена файлов без пути . Но вы не добавляете путь к rm
. Таким образом, он попытается удалить имена файлов из вашего подкаталога в вашем текущем/корневом каталоге.
Попробуйте
$ cd process_logs/; ls | grep -P '^some_pattern_matching_regex_goeshere.txt$' | xargs rm -f
Или
$ ls process_logs/ | grep -P '^some_pattern_matching_regex_goeshere.txt$' | xargs -i rm -f "process_logs/{}"
Поскольку интервал должен оставаться фиксированным, возможно, это означает, что весь макет фиксирован, и тогда это может быть то, что вы ищете, используя sed, который поддерживает -E, чтобы включить ERE, такие как GNU sed или OSX/BSD. сед:
$ sed -E 's/(.{17})A /\1RA/' file
ATOM 32 P RA 2 6.882 -5.338 6.560 1.00 0.00 P
ATOM 33 OP1 RA 2 7.505 -5.970 7.750 1.00 0.00 O
ATOM 34 OP2 RA 2 5.404 -5.201 6.610 1.00 0.00 O
TER
или с любым POSIX-кодом:
$ sed 's/\(.\{17\}\)A /\1RA/' file
ATOM 32 P RA 2 6.882 -5.338 6.560 1.00 0.00 P
ATOM 33 OP1 RA 2 7.505 -5.970 7.750 1.00 0.00 O
ATOM 34 OP2 RA 2 5.404 -5.201 6.610 1.00 0.00 O
TER
РЕДАКТИРОВАТЬ :ваш ввод, похоже, не соответствует стандарту pdb , который @bushman опубликовал ранее, но если это так, вот как вы можете использовать информацию из стандарта для создания массива f[]
полей по их тегам/именам, изменять их по их тегу/имени (в отличие от их относительного положения во вводе )и печатать их в том же формате с фиксированной шириной:
$ cat tst.awk
BEGIN {
# Record Format (copied from http://www.wwpdb.org/documentation/file-format-content/format33/sect9.html#ATOM)
#
# COLUMNS DATA TYPE FIELD DEFINITION
# -------------------------------------------------------------------------------------
flds[++numFlds]=" 1 - 6 Record name ATOM "
flds[++numFlds]=" 7 - 11 Integer serial Atom serial number."
flds[++numFlds]=" 13 - 16 Atom name Atom name."
flds[++numFlds]=" 17 Character altLoc Alternate location indicator."
flds[++numFlds]=" 18 - 20 Residue name resName Residue name."
flds[++numFlds]=" 22 Character chainID Chain identifier."
flds[++numFlds]=" 23 - 26 Integer resSeq Residue sequence number."
flds[++numFlds]=" 27 AChar iCode Code for insertion of residues."
flds[++numFlds]=" 31 - 38 Real(8.3) x Orthogonal coordinates for X in Angstroms."
flds[++numFlds]=" 39 - 46 Real(8.3) y Orthogonal coordinates for Y in Angstroms."
flds[++numFlds]=" 47 - 54 Real(8.3) z Orthogonal coordinates for Z in Angstroms."
flds[++numFlds]=" 55 - 60 Real(6.2) occupancy Occupancy."
flds[++numFlds]=" 61 - 66 Real(6.2) tempFactor Temperature factor."
flds[++numFlds]=" 77 - 78 LString(2) element Element symbol, right-justified."
flds[++numFlds]=" 79 - 80 LString(2) charge Charge on the atom."
for (fldNr=1; fldNr<=numFlds; fldNr++) {
fld = flds[fldNr]
cols = substr(fld,1,16)
gsub(/ /,"",cols)
n = split(cols,begEnd,/-/)
tag = substr(fld,31,13)
gsub(/ /,"",tag)
tags[fldNr] = tag
begs[tag] = begEnd[1]
wids[tag] = begEnd[n] - begEnd[1] + 1
# Uncomment this if interested in the values the arrays contain:
# print "<" fldNr "><" tags[fldNr] "><" begs[tag] "><" wids[tag] ">" | "cat>&2"
}
}
{
for (fldNr=1; fldNr<=numFlds; fldNr++) {
tag = tags[fldNr]
f[tag] = substr($0,begs[tag],wids[tag])
gsub(/^ +| +$/,"",f[tag])
}
}
f["resName"] == "A" { f["resName"] = "RA" } # this is where you can change a field by its tag/name
{
for (fldNr=1; fldNr<=numFlds; fldNr++) {
tag = tags[fldNr]
printf "%-*s", wids[tag], f[tag]
}
print ""
}
$
$ awk -f tst.awk file
ATOM 32 P RA 2 6.882 -5.338 6.560 1.00 0.00 P
ATOM 33 OP1 RA 2 7.505 -5.970 7.750 1.00 0.00 O
ATOM 34 OP2 RA 2 5.404 -5.201 6.610 1.00 0.00 O
TER
Очевидно, что это излишне для того, что вы пытаетесь сделать прямо сейчас, но это хороший общий подход, о котором следует помнить, и он решает проблему, с которой вы можете столкнуться при любом другом подходе, обсуждаемом до сих пор, с пустыми полями перед интересующим вас полем. дюйм
Если вы просто хотите получить красивый печатный табличный вывод с заменой столбцов, следующее дополнение к вашей команде awk
позволит добиться этого:
awk ' gsub("A","RA",$4){for (i=1;i<=NF;i++){printf("%-9s",$i)}print "" }' a.txt > b.txt
с выводом cat b.txt
, который выглядит как:
ATOM 32 P RA 2 6.882 -5.338 6.560 1.00 0.00 P
ATOM 33 OP1 RA 2 7.505 -5.970 7.750 1.00 0.00 O
ATOM 34 OP2 RA 2 5.404 -5.201 6.610 1.00 0.00 O
Если вы ищете более конкретное расстояние между каждым столбцом, вам придется отказаться от цикла printf
и назначить индивидуальное расстояние для каждого поля.
Если вы ищете очень быструю sed
альтернативу, вы всегда можете просто:
sed 's/ A /RA/' a.txt > b.txt
, но это заменит каждый «A» в файле на «RA», не ограничиваясь 4-м столбцом, поскольку sed
использует другой метод разделения полей, чем awk
. Тем не менее, использование приведенной выше команды sed
даст вам cat b.txt
, который будет выглядеть следующим образом:
ATOM 32 P RA 2 6.882 -5.338 6.560 1.00 0.00 P
ATOM 33 OP1 RA 2 7.505 -5.970 7.750 1.00 0.00 O
ATOM 34 OP2 RA 2 5.404 -5.201 6.610 1.00 0.00 O
Использованиеsed
sed -E "s/^(([^ ]+ +){3})A /\1RA /" file1
Прохождение
С начала строки ввода^
([^ ] +)
означает захватить группу ( )
как непрерывную последовательность не -пробелов [^ ]+
, за которой следует еще одна непрерывная последовательность пробелов+
Захватите эту группу для {3}
повторений, чтобы следующие символы были в вашем четвертом поле
Сгруппируйте все три повторения вместе, обернув( )
Если за этой «супергруппой», которая сейчас хранится в \1
, следует A
(, то есть A с 2 пробелами ), замените ее на \1RA
(, только с 1 завершающим пробелом, чтобы вы сохранили символ считать одинаково)
Метод -1 :GNU sed без обратных ссылок
$ sed -re '
h
s/\S+/\n&\n/4
s/\nA\n/RA/;t
g
' file
Метод -2 :GNU sed с обратными ссылками.
$ sed -re '
s/^(\s*(\S+\s+){3})(A(\s|$))/\1R\3/
' file
Обратите внимание, что оба решения sed можно сделать совместимыми с Posix, но это будет стоить чистоты кода и может привести к обратной косой черте.
Метод -3 :Perl использует awk-подобные поля, НО с изюминкой, этот хранит как значения полей, так и разделители. Таким образом, 4-е поле становится 8-м, а с массивом с нулевым индексом оно равно 7.
$ perl -F'/(\S+)/' -lane '
$F[7] =~ s/^A$/RA/;
print @F;\
' file