Я думаю, что этот awk
скрипт должен работать. Он делает все из скрипта, так как это самая простая настройка. Но см. далее альтернативу, которая позволяет обрабатывать ваш nextcounter как переменную оболочки:
BEGIN
{ getline counter < "nextcounter"; }
/TRANSID000/
{
replacement_string = sprintf("TRAN%05d", counter++);
gsub("TRANSID000", replacement_string);
print;
}
END
{ printf("%d\n", counter) > "nextcounter"; }
Вы можете вызвать его с помощью одного -вкладыша, подобного этому:
cat data | awk -- 'BEGIN { getline counter < "nextcounter"; } /TRANSID000/{ replacement_string = sprintf("TRAN%05d", counter++); gsub("TRANSID000", replacement_string); print; } END { printf("%d\n", counter) > "nextcounter"; }'
Обратите внимание:
TRAN000066
, т.е. имеющая всего 6 цифр,но тогда ваш образец вывода имеет строку типа TRAN00066
, т.е. с 5 цифрами. Я следовал вашему образцу вывода, но если вместо этого вам нужна точность 6 -цифр, просто измените строку TRAN%05d
наTRAN%06d
nextcounter
, был первым номером для замены. Если вместо этого вы хотите сначала увеличить число, просто замените часть counter++
на++counter
nextcounter
как файл, содержащий только одну строку, содержащую только числовое целое число. Если это не совсем так, вам нужно изменить скрипт BEGIN
и END
раздел Если вы предпочитаете , а не , чтобы сценарий awk обновлял ваш nextcounter
файл напрямую и вместо этого обрабатывал такое значение nextcounter как переменную оболочки, вам потребуется немного более сложная настройка, включающая использование временного файла. для хранения обновленного счетчика. Что-то вроде этого:
tempfile=$(mktemp) ; cat data | awk -v counter="${nextcounter:-0}" -v tempfile="${tempfile}" -- '/TRANSID000/{ replacement_string = sprintf("TRAN%05d", ++counter); gsub("TRANSID000", replacement_string) ; print; } END { printf("%d\n", counter) > tempfile; }' && read nextcounter < "${tempfile}" ; rm "${tempfile}"
Разобрано для объяснения:
tempfile=$(mktemp) \ # create temporary file
cat data | pipe data to awk...
awk -v counter="${nextcounter:-0}" -v tempfile="${tempfile}" -- \ # provide initial counter and tempfile to awk
'/TRANSID000/ \
{ replacement_string = sprintf("TRAN%05d", ++counter); \
gsub("TRANSID000", replacement_string) ; \
print; \
} \
END \
{ printf("%d\n", counter) > tempfile; }' \ # write updated counter to temporary file
&& read nextcounter < "${tempfile}" \ # read updated counter into ${nextcounter} shell variable
rm "${tempfile}"
Это ожидает начальный счетчик в ${nextcounter}
и обновляет ту же самую переменную в конце.
ЕСЛИ создание временных файлов невозможно, вы можете попробовать использовать файловые дескрипторы -поверх безымянных каналов, но для этого требуется Bash v3+ и система, позволяющая открывать каналы в режиме чтения/записи. Linux это позволяет, MacOS — нет, не знаю о других Unix -es.
Было бы похоже:
exec 9<> <(:) ; cat data | awk -v counter="${nextcounter:-0}" -- '/TRANSID000/{ replacement_string = sprintf("TRAN%05d", ++counter); gsub("TRANSID000", replacement_string); print; } END { printf("%d\n", counter) > "/dev/fd/9"; }' && read nextcounter <&9 ; exec 9<&-
В разобранном виде:
exec 9<> <(:) # open fd 9 onto unnamed pipe R/W
cat data | \
awk -v counter="${nextcounter:-0}" -- \
'/TRANSID000/ \
{ replacement_string = sprintf("TRAN%05d", ++counter); \
gsub("TRANSID000", replacement_string); \
print; } \
END \
{ printf("%d\n", counter) > "/dev/fd/9"; }' \ # write updated counter to fd 9
&& read nextcounter <&9 # read updated counter from fd 9 into ${nextcounter} shell variable
exec 9<&- # close fd 9
Хакерская попытка использовать Perl в помощь. Посмотрите, как он заменяет uid:1001
на user:bob
.
# ss -ntel
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 10 0.0.0.0:12345 0.0.0.0:* uid:1001 ino:29109 sk:5e <->
LISTEN 0 100 127.0.0.1:25 0.0.0.0:* ino:18771 sk:2 <->
LISTEN 0 128 0.0.0.0:111 0.0.0.0:* ino:16606 sk:3 <->
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* ino:20128 sk:4 <->
LISTEN 0 10 [::]:12345 [::]:* uid:1001 ino:29108 sk:61 v6only:1 <->
LISTEN 0 128 [::]:111 [::]:* ino:16609 sk:5 v6only:1 <->
LISTEN 0 128 *:80 *:* ino:18314 sk:6 v6only:0 <->
LISTEN 0 128 [::]:22 [::]:* ino:20130 sk:7 v6only:1 <->
# ss -ntel|perl -pne 'if(/uid:(\d+)/){@a=getpwuid($1);s/uid:(\d+)/user:$a[0]/}'
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 10 0.0.0.0:12345 0.0.0.0:* user:bob ino:29109 sk:5e <->
LISTEN 0 100 127.0.0.1:25 0.0.0.0:* ino:18771 sk:2 <->
LISTEN 0 128 0.0.0.0:111 0.0.0.0:* ino:16606 sk:3 <->
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* ino:20128 sk:4 <->
LISTEN 0 10 [::]:12345 [::]:* user:bob ino:29108 sk:61 v6only:1 <->
LISTEN 0 128 [::]:111 [::]:* ino:16609 sk:5 v6only:1 <->
LISTEN 0 128 *:80 *:* ino:18314 sk:6 v6only:0 <->
LISTEN 0 128 [::]:22 [::]:* ino:20130 sk:7 v6only:1 <->
#
Примечание. :Я проверил исходный код и, похоже, в ss
нет ничего родного для достижения этой цели.