Я работаю с данными в текстовом файле и не могу найти способ с помощью sed выбрать подстроку в фиксированной позиции и заменить ее.
Вот что у меня есть:
X|001200000000000000000098765432|1234567890|TQ
Это то, что мне нужно:
‘X’,’00000098765432’,’1234567890’,’TQ’
Следующий код в sed дает нужную мне подстроку (00000098765432), но не перезаписывает нужную позицию
echo “ X|001200000000000000000098765432|1234567890|TQ” | sed “s/
*//g;s/|/‘,’/g;s/^/‘/;s/$/‘/“
Не могли бы вы помочь мне?
При извлечении данных с помощью конвейера я хочу удалить 16 символов перед второй позицией. образец: от 001200000000000000000098765432 до 00000098765432
В вашем коде и примере используются «умные кавычки», пожалуйста, редактировать те, кто вместо этого использует простые кавычки ASCII, ' и ".





Вместо sed я бы использовал awk для этого.
echo "X|001200000000000000000098765432|1234567890|TQ" | awk 'BEGIN {FS = "|";OFS = ","} {print $1,substr($2,17,14),$3,$4}'
Дает вывод:
X,00000098765432,1234567890,TQ
Вот как это работает:
FS = Разделитель полей (во вводе)
OFS = разделитель полей вывода (так, как вы хотите, чтобы вывод был разделен)
BEGIN -> думайте об этом как о месте, где устанавливаются конфигурации. Он запускается только один раз. Итак, вы говорите, что хотите, чтобы вывод был разделен запятой, а ввод - с разделителем канала.
substr($2,17,14) -> Возьмите $2 (т.е. второе поле — awk начинает отсчет с 1 — и затем примените к нему подстроку. 17 означает начальную позицию символа, а 14 означает количество символов с этой позиции и далее)
На мой взгляд, это намного удобнее для чтения и обслуживания, чем версия sed, которая у вас есть.
substr($2,17,14) может быть просто substr($2,17), вам не нужно указывать количество символов, если вы просто хотите перейти в конец строки.
Если вы хотите поставить кавычки, я бы все равно использовал awk.
$: awk -F'|' 'BEGIN{q = "\047"} {print q $1 q","q substr($2,17,14) q","q $3 q","q $4 q"\n"}' <<< "X|001200000000000000000098765432|1234567890|TQ"
'X','00000098765432','1234567890','TQ'
Если вы просто хотите использовать sed, обратите внимание, что вы сказать выше хотите удалить 16 символов, но на самом деле вы удаляете только 14.
$: sed -E "s/^(.)[|].{14}([^|]+)[|]([^|]+)[|]([^|]+)/'\1','\2','\3','\4'/" <<< "X|0012000000000000000098765432|1234567890|TQ"
'X','00000098765432','1234567890','TQ'
Использование sed
$ sed "s/|\(0[0-9]\{15\}\)\?/','/g;s/^\|$/'/g" input_file
'X','00000098765432','1234567890','TQ'
awk -v del1 = "\047" \
-v del2 = "," \
-v start = "3" \
-v len = "17" \
'{
gsub(substr($0,start+1,len),"");
gsub(/[\|]/,del1 del2 del1);
print del1$0del1
}' input_file
'X',00000098765432','1234567890','TQ'
@EdMorton: изменено на len
Используя любой POSIX awk:
$ echo 'X|001200000000000000000098765432|1234567890|TQ' |
awk -F'|' -v OFS = "','" -v q = "'" '{sub(/.{16}/,"",$2); print q $0 q}'
'X','00000098765432','1234567890','TQ'
не так элегантно, как я надеялся, но он выполняет свою работу:
'X','00000098765432','1234567890','TQ'
# gawk profile, created Mon May 9 21:19:17 2022
# BEGIN rule(s)
'BEGIN {
1 _ = sprintf("%*s", (__ = +2)^++__+--__*++__,__--)
1 gsub(".", "[0-9]", _)
1 sub("$", "$", _)
1 FS = "[|]"
1 OFS = "\47,\47"
}
# Rule(s)
1 (NF *= NF == __*__) * sub(_, "|&", $__) * \
sub("^.*[|]", "", $__) * sub(".+", "\47&\47") }'
Протестировано и подтверждено, работает на gnu gawk 5.1.1, mawk 1.3.4, mawk 1.9.9.6 и macosx nawk
— The 4Chan Teller
Похоже, вы пытаетесь удалить первые 4 символа. Это правильно?