Это также может быть вызвано невозможностью привязки к порту на локальной стороне.
ssh -Nn -L 1234:remote:5678 user@remote
Эта команда пытается связать прослушиваемый порт 1234 на локальном компьютере, который сопоставляется со службой на порту 5678 на удаленном компьютере.
Если порт 1234 на локальном компьютере уже используется другим процессом, (возможно, фоновый ssh -f сеанс ), тогда ssh не сможет прослушивать этот порт и туннель не будет работать..
Проблема в том, что это сообщение об ошибке может означать несколько вещей, а фраза «административно запрещена» иногда дает неверное представление. Таким образом, в дополнение к проверке DNS, брандмауэров между локальным и удаленным и конфигурации sshd _, проверьте, не используется ли уже локальный порт. Используйте
lsof -ti:1234
, чтобы выяснить, какой процесс запущен на 1234. Вам может понадобиться sudo, чтобы lsof вывел список процессов, принадлежащих другим пользователям. Затем вы можете использовать
ps aux | grep <pid>
, чтобы выяснить, что это за процесс.
Чтобы получить все это одной командой:
ps aux | grep "$(sudo lsof -ti:1234)"
Еще один awk
.
Я задавался вопросом, не будет ли итерация по ассоциативному массиву for (f in fields)
скремблировать вывод поля, но, проведя несколько тестов с шириной до 20 полей, похоже, что нет.
Предположим, что ваши заголовки находятся в строке 1, данные отсортированы (в соответствии с сообщением )и что у вас есть масса данных, которые вы не хотите хранить в памяти сразу
awk 'BEGIN{getline; split($0,out,"\t"); old=$1}
old!=$1{for (o in out) printf "%s\t", out[o]; print""; delete out;old=$1}
{split($0,tmp,"\t"); for (t in tmp) out[t]=(t==1)?tmp[t]:out[t]+tmp[t]}
END{for (o in out) printf "%s\t", out[o];}' file
Этот вход
head c1 c2 c3
H1 -0.71
H1 2
H1 3
H2 11 12
H2 13
Дает
head c1 c2 c3
H1 -0.71 2 3
H2 11 12 13
Прохождение
Возьмите первую строку и запомните первое поле вold
awk 'BEGIN{getline; split($0,out,"\t"); old=$1}
Если первое поле в следующей записи отличается от последнего (нового заголовка ), то последняя агрегация завершена, поэтому распечатайте ее, очистите массив агрегации out
и отметьте, что вы находитесь в новый комплектold=$1
old!=$1{for (o in out) printf "%s\t", out[o]; print""; delete out;old=$1}
Разделить $0
на массив tmp
, выполнить итерацию по массиву, добавив значение tmp
к out
, если только это не столбец заголовка, когда вы просто берете значение
{split($0,tmp,"\t"); for (t in tmp) out[t]=(t==1)?tmp[t]:out[t]+tmp[t]}
Очистить последний набор записей, хранящихся в out
вEND
END{for (o in out) printf "%s\t", out[o];}' file
Вот так:
$ awk -F"\t" '{if(NR==1){ cols=NF; print; } else{for(i=2;i<=NF;i++){if(length($i)>0){data[$1][i]=$i}}}}END{for(id in data){ printf "%s",id; for(i=2;i<=cols;i++){printf "\t%s", data[id][i]} print ""}}' file
OG FC_AG_NICO FC_AG_ZEA FC_AG_BRAS FC_MB_NICO FC_MB_ZEA FC_MB_BRAS FC_TN_NICO FC_TN_ZEA FC_TN_BRAS FC_SL_NICO FC_SL_ZEA FC_SL_BRAS FC_SE_NICFC_SE_ZEA FC_SE_BRAS
OG0004400 -0.787302663 -0.710790578 0.663333543 -0.360799687 -0.0958126 0.056722264 -1.77626686 -0.971114297 0.707963822 -0.373838773 0.277055943 0.481626213 -1.659046364 -1.019969932
OG0004402 -0.304209641 -0.259080399 0.44366888 0.253000346 0.338511357 -0.121760564 -0.274550145 0.1933262 0.374095809 0.442748804 0.042958499
Или,немного легче читать:
awk -F"\t" '{
## Print the headers and store the number of columns.
if(NR==1){
cols=NF;
print;
}
else{
## Iterate over all columns, starting from the 2nd.
for(i=2;i<=NF;i++){
## If this one isn't empty, store it.
if(length($i)>0){
data[$1][i]=$i
}
}
}
}
## After reading everything, print.
END{
for(id in data){
printf "%s",id;
for(i=2;i<=cols;i++){
printf "\t%s", data[id][i]
}
print ""
}
}' file
Обратите внимание, что это предполагает, что каждый ID (1-е поле )имеет значение для каждого столбца в одной строке и только в одной строке. Если у вас могут быть пустые столбцы для идентификатора, вам понадобится немного другой подход.