Каждый процесс имеет свою собственную среду, скопированную с родителя. Если родитель является оболочкой, существует понятие экспортных переменных, которое нужно рассмотреть, но это не применяется, когда Вы имеете дело с exec()
и т.д. непосредственно. LOGNAME
переменная обычно устанавливается оболочкой входа в систему, Вы просто видите оставшееся значение, которое не было сброшено. Так, Вы видите дочернюю среду. В некоторых системах Вы не можете легко получить доступ к родителю (или другой процесс) среда, на Linux можно сделать это легко (подвергающийся полномочиям) через /proc
)
Можно, вероятно, воспроизвести эффект, который Вы видите путем попытки обоих su
и su -
, последний инициализирует среду входа в систему оболочки, которая (почти наверняка) сбросит LOGNAME
среди других вещей первый оставит это нетронутым.
Используя env
команда является одним способом получить чистую среду при запуске нового процесса с командной строки, необходимо проверить execle()
документация относительно Вашей системы, чтобы видеть, как сделать что-то подобное.
Если у вас есть только 4 строки после [part1]
, вы можете используйте параметр -A4
с grep
:
cat ${file} | grep -A4 "part1" | cut -d'=' -f2`
В общем случае (более 4 строк после [part1]) используйте sed
, чтобы получить текст между двумя частями :
cat ${file} | sed -n "/part1/,/part2/p" | head -n-1
head
- это удалить дополнительный part2
в конце
Как terdon сказал, что вам не нужно использовать cat
, вы вместо этого можно сделать следующее:
grep -A4 "part1" ${file} | cut -d'=' -f2`
ИЛИ:
sed -n "/part1/,/part2/p" ${file} | head -n-1
Нужно использовать более сложный инструмент для разбора файла. Например, awk
:
#!/bin/sh
getCalibDate()
{
file="${1}"
value=$(awk '/\[part/{a++}(a<2 && /Val/){print $NF}' ${file})
for v in $value
do
echo $v
done
}
getCalibDate ${1}
Здесь переменная a
увеличивается каждый раз, когда строка совпадает с [часть
. Затем, последнее поле ($NF
) выводится, когда строка совпадает с Val
, но только если a
меньше 2, только если мы находимся в 1-ой секции.
Чтобы получить целые строки из первой части:
awk '$1 ~ /^\[/ {n++;next} n==1'
Чтобы просто распечатать правую часть первой =
:
awk '$1 ~ /^\[/ {n++;next} n==1 {sub(/^[^=]*=[[:blank:]]*/,""); print}'
и используйте следующее:
sed -n -e '/\[part1\]/,/\[part2\]/p' FILE |sed -e '1d;$d'| awk -F "=" '{print $2}'
OUTPUT is:
a
val1
a
val1
sed -n '/part2/q;s/[^=]*=//p' \
<<\DATA
<Title>
[part1]
A.File = a
A.Val = val1
B.File = a
B.Val = val1
[part2]
A.File = a1
A.Val = val2
B.File = a
B.Val = val1
DATA
a
val1
a
val1
Это должно помочь. Он немедленно q
uit входной файл, когда впервые встретит строку part2 где-нибудь во входных данных. Это означает, что он даже не пытается прочитать части файла, которые вам не нужны, что должно сделать его очень эффективным.
-n
отключает автоматическую печать, поэтому sed
печатает только то, что определенно указано в p
rint. Единственный раз, когда ему определенно предлагается печатать, это когда он может успешно удалить последовательность из 0 или более символов, не являющихся =
, и один символ, который является =
.
Если вы хотите вместо этого напечатать всю совпадающую строку, вы можете сделать:
sed -n '/part2/q;/=/p'
Здесь есть несколько хороших ответов,
но я вижу только один, который включает в себя часть проблемы Val
,
и неясно, правильно ли это.
Я согласен с тем, что awk
- «замечательный инструмент», но здесь в нем нет необходимости;
Я считаю, что эта команда sed
:
sed -n '/\[part1\]/,/\[part2\]/s/.*Val.*=//p' "$file"
, вероятно, делает то, что желает.
Как и другие решения sed -e '/ \ [part1 \] /, / \ [part2 \] / p'
( Сетевик
и Бэби ),
это легко адаптировать для выбора любого раздела.
(Вы, конечно, должны знать его имя; если вы знаете только его порядковый номер,
вы можете адаптировать ответ Тердона
или ответ Гленна Джекмана ,
оба из которых учитывают разделы, а не ищут конкретное имя.)
Если вы не знаете название следующего раздела, вы можете ввести, например,
sed -n '/\[part42\]/,/\[part/s…' "$file"
.
Мой единственный мета-вопрос касается части вопроса cut -d '=' -f2
.
Если строка ввода, из которой мы извлекаем данные, содержит несколько =
символов
после Val
(т.е. значение поля содержит =
символа (ов)), например,
Einstein.Val = E=mc^2
, то приведенная выше команда cut
извлечет только текст между первая и вторая =
(т.е. значение поля до (но не включая) первого =
), например, E
.
Команда sed
, которую я представил выше, будет извлекать только текст
после последнего =
(например, mc ^ 2
).
Чтобы получить все после первого =
(например, E = mc ^ 2
), используйте
sed -n '/\[part1\]/,/\[part2\]/s/.*Val[^=]*=//p' "$file"
Чтобы имитировать поведение разреза
(например, E
), используйте
sed -n '/\[part1\]/,/\[part2\]/s/.*Val[^=]*=\([^=]*\).*/\1/p' "$file"
Обратите внимание, что мой подход предполагает, что данные выглядят
по крайней мере, в целом как на иллюстрации в вопросе;
то есть, по крайней мере, один =
появляется где-то справа от строки Val
.
Соответственно, все мои решения будут игнорировать ввод вроде
Girl.Name = Valerie
Valerie Bertinelli
, даже если он находится между [part1]
и [part2]
.