Можно всегда использовать LD_PRELOAD
обманите к тому, чтобы Linux подражал пути BSD. fddup.c
:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int whichfd(const char *pathname)
{
unsigned int fd;
if (sscanf(pathname, "/dev/fd/%u", &fd) == 1)
return fd;
else
return -1;
}
int open(const char *pathname, int flags, mode_t mode)
{
static int (*orig)(const char *, int, mode_t) = 0;
int fd = whichfd(pathname);
if (fd >= 0)
return dup(fd);
else {
if (!orig)
orig = dlsym(RTLD_NEXT,"open");
if (!orig) abort();
return orig(pathname, flags, mode);
}
}
FILE *fopen(const char *path, const char *mode)
{
static FILE *(*orig)(const char *, const char *) = 0;
int fd = whichfd(path);
if (fd >= 0)
return fdopen(dup(fd), mode);
else {
if (!orig)
orig = dlsym(RTLD_NEXT,"fopen");
if (!orig) abort();
return orig(path, mode);
}
}
(Вы, возможно, должны перенестись больше как freopen()
).
gcc -Wall -fPIC -shared -o fddup.so fddup.c -ldl
И затем:
socat TCP:localhost:22 'EXEC:env LD_PRELOAD=./ddup.so cat /dev/fd/0,nofork'
Обратите внимание, что Linux и BSD существенно отличаются. Это не так, что Вы не можете открыться /dev/fd/0
когда это - сокет, но это /dev/fd/x
символьная ссылка на файл, который открыт на fd x. Вы не можете сделать open()
на сокете, который не имел бы смысла. open("/dev/fd/x")
нисколько не a dup(x)
как в BSD. Похоже на него, когда файл является каналом, но это даже не затем, это - в действительности то же как как открытие именованного канала (можно даже открыть его в другом режиме (чтение по сравнению с записью) для получения другого конца канала).
Оба подхода имеют свои за и против. Это звучит мне, Ваше приложение должно взять fd числа в качестве аргументов, не используют /dev/fd/x
который является взломом во-первых так или иначе и например заставил бы Вас тратить впустую fds.
С awk
:
$ awk 'FNR%2==0{sub(255,1)}1' file
myName_tx_1 VARCHAR(255)
myName_in_1 VARCHAR(1)
myName_tx_2 VARCHAR(255)
myName_in_2 VARCHAR(1)
myName_tx_3 VARCHAR(255)
myName_in_3 VARCHAR(1)
myAddress_tx_1 VARCHAR(255)
myAddress_in_2 VARCHAR(1)
Объяснение
FNR% 2 == 0
соответствует только четным строкам. 255
на 1
, sub (255,1)
. 1
- истинное условие, make awk
print $ 0
. Та же логика может использоваться с другими инструментами, такими как perl
:
perl -pe 's/255/1/ unless $. % 2' file
С помощью sed
вы можете:
sed -e 'n;s/255/1/' file
Обновить
С вашими требованиями к обновлению, мы можем немного изменить решение.
С awk
:
awk '/_in_[0-9]/{sub(255,1)}1' file
С sed
:
sed -e '/_in_[0-9]/{s/255/1/}' file
С perl
:
perl -pe 's/255/1/ if /_in_[0-9]/' file
В GNU sed вы можете указать адреса строк в формате first ~ step
, чтобы изменять каждую вторую строку, начиная со второй, вы могли бы использовать адрес 2 ~ 2
, например.
$ sed '2~2 s/(255)/(1)/' file
myName_tx_1 VARCHAR(255)
myName_in_1 VARCHAR(1)
myName_tx_2 VARCHAR(255)
myName_in_2 VARCHAR(1)
myName_tx_3 VARCHAR(255)
myName_in_3 VARCHAR(1)
myAddress_tx_1 VARCHAR(255)
myAddress_in_2 VARCHAR(1)
Есть
sed '/_in_/ s/255/1/'
, что означает: для совпадения строк /_в__/
искать 255
и заменять на 1
.