У меня есть входная строка, как показано ниже:
VAL:1|b:2|c:3|VAL:<har:[email protected]>; tag=vy6r5BpcvQ|VAl:1234|name:mnp|VAL:91987654321
Таким образом, имеется более 1000 строк.
Я хочу получить значение первого параметра, то есть поля a
и поля d
, но для поля d
я хочу только har:[email protected]
.
Я пробовал так:
cat $filename | grep -v Orig |sed -e 's/['a:','d:']//g' |awk -F'|' -v OFS=',' '{print $1 "," $4}' >> $NGW_DATA_FILE
Результат, который я получил, ниже:
1,<[email protected]>; tag=vy6r5BpcvQ
Я хочу, чтобы это было так,
1,har:[email protected]
Где я допустил ошибку и как ее решить?
иногда я могу получить значение в том же имени поля, что и val: вместо a и d, тогда как я могу получить его значения
Обновлено: в соответствии с изменением OP в Input_file и комментариями OP, теперь добавлено следующее.
awk '
BEGIN{ FS = "|"; OFS = "," }
{
sub(/[^:]*:/,"",$1)
gsub(/^[^<]*|; .*/,"",$4)
gsub(/^<|>$/,"",$4)
print $1,$4
}' Input_file
С показанными образцами, не могли бы вы попробовать следовать, написать и протестировать показанные образцы в GNU awk
.
awk '
BEGIN{
FS = "|"
OFS = ","
}
{
val = ""
for(i=1;i<=NF;i++){
split($i,arr,":")
if (arr[1]= = "a" || arr[1]= = "d"){
gsub(/^[^:]*:|; .*/,"",$i)
gsub(/^<|>$/,"",$i)
val=(val?val OFS:"")$i
}
}
print val
}
' Input_file
Объяснение: Добавлено подробное объяснение вышеизложенного.
awk ' ##Starting awk program from here.
BEGIN{ ##Starting BEGIN section of this program from here.
FS = "|" ##Setting FS as pipe here.
OFS = "," ##Setting OFS as comma here.
}
{
val = "" ##Nullify val here(to avoid conflicts of its value later).
for(i=1;i<=NF;i++){ ##Traversing through all fields here
split($i,arr,":") ##Splitting current field into arr with delimiter by :
if (arr[1]= = "a" || arr[1]= = "d"){ ##Checking condition if first element of arr is either a OR d
gsub(/^[^:]*:|; .*/,"",$i) ##Globally substituting from starting till 1st occurrence of colon OR from semi colon to everything with NULL in $i.
val=(val?val OFS:"")$i ##Creating variable val which has current field value and keep adding in it.
}
}
print val ##printing val here.
}
' Input_file ##Mentioning Input_file name here.
Привет, сэр, спасибо за ответ, это работает для этого случая, у меня есть одно сомнение, что если вместо A и D я получил одно и то же имя поля, как и оба значения присутствуют в D: 1 | D: <har: 919876543210 @abc.com>; tag=vy6r5BpcvQ вот так, что мне нужно изменить, так как файл может содержать огромные данные
@mark, извините, но это неясно, пожалуйста, приведите более наглядный пример.
хорошо, если дело обстоит так: -- a:1|b:2|c:3|a:<har:[email protected]>; тег=vy6r5BpcvQ| если ключ 'a' для первой и четвертой записи
@mark, хорошо, так что же тогда будет условием для печати этих значений? Пожалуйста, подтвердите один раз.
Я обновлю свой вопрос, я добавлю весь набор данных, которые я получаю
@mark, то есть вы всегда хотите печатать 1-й столбец ИЛИ это VAL
с одной цифрой, которую вы хотите напечатать? Пожалуйста, подтвердите один раз.
Как вы можете видеть в моем примере ввода, есть несколько полей с именем VAL в качестве ключа, я хотел, чтобы его значение присутствовало в первой позиции и 4-й позиции и игнорировало остальные, т.е. 1,<har:[email protected]> , 1 - это значение из первого ключа VAL, а второе - значение из VAL, присутствующего в 4-й позиции, есть много мест, где присутствует VAL, я хочу игнорировать это
@mark, пожалуйста, проверьте мой ответ EDIT один раз и дайте мне знать, работает ли это для вас?
Да, это сработало, я внес небольшое изменение gsub(/^[^<]*|; .*/,"",$1) sub(/[^:]*:/,"",$4) с этим сработало также, спасибо, сэр
Вы также можете попробовать этот скрипт AWK:
cat file
VAL:1|b:2|c:3|VAL:<har:[email protected]>; tag=vy6r5BpcvQ|VAl:1234|name:mnp|VAL:91987654321
awk -F '[|;]' '{
s = ""
for (i=1; i<=NF; ++i)
if ($i ~ /^VAL:/) {
gsub(/^[^:]+:|[<>]*/, "", $i)
s = (s == "" ? "" : s "," ) $i
}
print s
}' file
1,har:[email protected]
Привет, сэр, спасибо за решение, здесь доступ к полям a и d и выполнение фильтрации, у меня есть одно сомнение, что если вместо двух разных полей a и d ввод изменится на a:1|b:2|c:3 |a:<har:[email protected]>; tag=vy6r5BpcvQ, как это, то как его отфильтровать, так как может быть несколько полей, имя которых начинается с одного и того же поля, например d
@mark wrt I have one doubt ...
- у вас есть "вопрос", а не "сомнение". Сомнение означает, что вы не верите тому, что вам сказали, вопрос просто означает, что вам нужна информация о чем-то. Это распространенная ошибка в английском языке, на котором говорят в Индии, см. может-сомневаться-иногда-значить-вопрос. Ничего страшного, конечно, просто подумал, что вы хотели бы знать.
Вы можете сделать то же самое с sed
довольно легко, используя расширенное регулярное выражение, две группы захвата и две обратные ссылки, например.
sed -E 's/^[^:]*:(\w+)[^<]*[<]([^>]+).*$/\1,\2/'
Объяснение
's/find/replace/'
стандартная замена, где стоит find
;^[^:]*:
с начала пропустить первый ':'
, затем(\w+)
захватить один или несколько символов слова ([a-zA-Z0-9_]
), затем[^<]*[<]
использовать ноль или более символов не '<'
, затем '<'
, затем([^>]+)
захватывать все не '>'
, а.*$
отбросить все оставшиеся символы в строке, тогда replace
\1,\2
повторно вставьте захваченные группы через запятую.Пример использования/вывода
$ echo 'a:1|b:2|c:3|d:<har:[email protected]>; tag=vy6r5BpcvQ|' |
sed -E 's/^[^:]*:(\w+)[^<]*[<]([^>]+).*$/\1,\2/'
1,har:[email protected]
Если вы все равно используете Awk, выполняйте всю эту обработку в Awk.