简体   繁体   English

awk变量在bash中打印为选项

[英]awk variables print as options in bash

I'm trying to make a script which reads your firefox profile.ini file, gives you options for which profile you want to unlock and execute a simple rm on the .lock file of the given profile (useful when you run multiple firefox sessions between workstations in different buildings and you did not logout correctly 我正在尝试制作一个脚本,该脚本读取您的firefox profile.ini文件,为您提供要解锁的配置文件的选项,并在给定配置文件的.lock文件上执行一个简单的rm(当您在两次之间运行多个firefox会话时很有用不同建筑物中的工作站,而您未正确注销

I have the following file profile.ini for example 我有以下文件profile.ini例如

[General]
StartWithLastProfile=0

[Profile0]
Name=default
IsRelative=1
Path=rkfddmkn.default
Default=1

[Profile1]
Name=NX
IsRelative=1
Path=sf18055j.NX

[Profile14]
Name=gutter
IsRelative=1
Path=sf18055judsfsdfdfds.gutter

[Profile556]
Name=Jerusalem
IsRelative=1
Path=234920fgffdg38.Jerusalem

And this is the first part 这是第一部分

ini=$HOME/.mozilla/firefox/profiles.ini
The script checks if profiles.ini exists otherwise exit 
    if [ -f $ini ]
            then
The script reads the profiles.ini file and return multiple profiles as options followed by the name of the profiles

profiles=`cat $ini | grep "Profile[0-9*]"`
echo $profiles | awk -v RS=" " '{print}'
names=`cat $ini | grep Name | sed s/Name=/\/`
echo $names | awk -v RS=" " '{print}'
echo $options = $profiles . ' ' . $names; | awk -v RS=" " '{print}'

I'm not sure if I'm going down the right path. 我不确定我是否走正确的道路。 How can I prompt the user to select an option by pairing the awk strings ? 如何通过配对awk字符串提示用户选择一个选项?

A native-bash parser that breaks the relevant part of your input file into three associative arrays might look something like the following: 将输入文件的相关部分分为三个关联数组的本机bash解析器可能类似于以下内容:

#!/usr/bin/env bash

set -x; PS4=':$LINENO+'

section_re='^\[Profile(.*)\][[:space:]]*$'
kv_re='^([[:alnum:]]+)=(.*)'

declare -A profilesByName=( )
declare -A profileNames=( )
declare -A profilePaths=( )

current_section=
while IFS= read -r line; do : line="$line"
  [[ $line =~ $section_re ]] && { current_section=${BASH_REMATCH[1]}; continue; }
  [[ $line =~ $kv_re ]] || continue
  [[ $current_section ]] || continue ## ignore k/v pairs if not in a section
  key=${BASH_REMATCH[1]}; value=${BASH_REMATCH[2]}
  case $key in
    Name) profileNames[$current_section]=$value
          profilesByName[$value]=$current_section ;;
    Path) profilePaths[$current_section]=$value ;;
  esac
done

Then, if you want to delete the lockfile associated with a given profile name, it becomes as simple as: 然后,如果要删除与给定的配置文件名称关联的锁文件,则它变得非常简单:

deleteLockForName() {
  local desiredName=$1
  local selectedProfile selectedPath
  selectedProfile=${profilesByName[$desiredName]}
  [[ $selectedProfile ]] || { echo "ERROR: No profile with name $desiredName found" >&2; return 1; }
  selectedPath=${profilePaths[$selectedProfile]}
  echo "Deleting $selectedPath.lck" >&2
  rm -f -- "$selectedPath.lck"
}

...as used in: ...用于:

deleteLockForName Jerusalem

You can see it running at https://ideone.com/d0QFYa -- in the above example invocation, emitting Deleting 234920fgffdg38.Jerusalem.lck . 您可以在https://ideone.com/d0QFYa上看到它运行-在以上示例调用中,发出Deleting 234920fgffdg38.Jerusalem.lck

@CharlesDuffy is always a tough act to follow (try it...), but I took a somewhat different approach to solving your problem. @CharlesDuffy总是很难遵循(尝试...),但是我采用了一些不同的方法来解决您的问题。

First, you don't need to deal with $HOME/.mozilla/firefox/profiles.ini at all. 首先,您根本不需要处理$HOME/.mozilla/firefox/profiles.ini All you need to deal with is those profiles that have an existing lock symlink within their profile directory. 您只需要处理在配置文件目录中具有现有lock符号链接的那些配置文件。 So create an array just holding the names of the directories with with a lock symlink present to display to the user to remove. 因此,创建一个仅包含目录名称的数组,并带有一个lock符号链接,以显示给用户删除。 You can do that with find and sed in a simple command-substitution , eg 您可以使用findsed通过简单的命令替换来实现 ,例如

#!/bin/bash

moz="$HOME/.mozilla/firefox"

## locate all lockfile links that exist below "$moz"
readarray -t lockfiles < <(find "$moz" -type l -name lock -printf '%P\n')

Next, the select loop in bash will create a numbered menu with entries being the profile directories in your lockfiles array. 接下来,bash中的select循环将创建一个带编号的菜单,其中的条目是您的lockfiles数组中的配置文件目录。 The user can select the number corresponding to the profile directory name to remove ( unlink ) the lock symlink in that directory. 用户可以选择与配置文件目录名称相对应的数字,以删除( unlink )该目录中的lock符号链接。 For example: 例如:

## set prompt for select menu
PS3="Selection: "

## prompt
printf "\nThe following lockfiles found, select to remove, Quit to end:\n\n"

## create menu listing existing lockfile links
select lockname in "${lockfiles[@]%/*}" "Quit"; do 
    [ "$lockname" = "Quit" ] && break
    if [ -h "$moz/$lockname/lock" ]; then
        printf "\ndeleting lock %s\n" "$moz/$lockname/lock"
        ## uncomment to actually remove link
        # unlink "$moz/$lockname/lock"
        break
    else
        printf "\nerror: invalid selection.\n" >&2
    fi
done

( note: setting PS3 controls the prompt displayed by the select loop, instead of the generic #? . Also note the /lock was trimmed from the contents of the array to display only the profile directory name in the select loop declaration with "${lockfiles[@]%/*}" ) 注意:设置PS3控制select循环显示的提示,而不是通用的#?还要注意, /lock是从数组的内容中剪裁出来的,以在select循环声明中仅使用"${lockfiles[@]%/*}"

Putting it altogether, you would have: 综上所述,您将拥有:

#!/bin/bash

moz="$HOME/.mozilla/firefox"

## locate all lockfile links that exist below "$moz"
readarray -t lockfiles < <(find "$moz" -type l -name lock -printf '%P\n')

## set prompt for select menu
PS3="Selection: "

## prompt
printf "\nThe following lockfiles found, select to remove, Quit to end:\n\n"

## create menu listing existing lockfile links
select lockname in "${lockfiles[@]%/*}" "Quit"; do 
    [ "$lockname" = "Quit" ] && break
    if [ -h "$moz/$lockname/lock" ]; then
        printf "\ndeleting lock %s\n" "$moz/$lockname/lock"
        ## uncomment to actually remove link
        # unlink "$moz/$lockname/lock"
        break
    else
        printf "\nerror: invalid selection.\n" >&2
    fi
done

Example Use/Output 使用/输出示例

$ bash ff_rm_lock.sh

The following lockfiles found, select to remove, Quit to end:

1) 3cblo6ag.dcr_new
2) Quit
Selection: 1

deleting lock /home/david/.mozilla/firefox/3cblo6ag.dcr_new/lock

or using "Quit" leaving all lock symlinks in place: 或使用"Quit"将所有lock符号链接保留在原位:

$ bash ff_rm_lock.sh

The following lockfiles found, select to remove, Quit to end:

1) 3cblo6ag.dcr_new
2) Quit
Selection: 2

( note: you must uncomment the line unlink "$moz/$lockname/lock" to actually remove the link -- I commented it to allow testing without removing my Firefox lockfile) 注意:您必须取消注释unlink "$moz/$lockname/lock"才能真正删除该链接-我评论说,允许进行测试而无需删除我的Firefox unlink "$moz/$lockname/lock"文件)

A different approach, but given your problem description, this should eliminate listing profiles with not associate lock symlink present. 一种不同的方法,但是根据您的问题描述,这应该消除没有关联lock符号链接的列表配置文件。 Let me know if you have questions. 如果您有任何问题,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM