0

I have a text file which looks like this:

... unique_trigger = item1 item2 item3 ... itemN unique_end_trigger ... 

Is there a quick (maybe on-liner if possible) bash script I could use to parse the file and pipe item1 item2 item3... into another command? The number of items is not determined. I looked at other bash scripts to read variables out of a file but they either source it, parse each item manually (predetermined list length) or assign a environment variable to each item based on its name (which is not my case). I am looking for something like this:

parse_command file.txt | other_command 
5
  • you'll increase the chances of receiving a usable answer if you provide a sample of the actual data; does item contain white space or embedded linefeeds? what do the lines before/after the unique_trigger section look like; do all item entries have a leading = or just the first one? are there any lines in the unique_trigger section that should not be printed? Commented May 6, 2022 at 16:11
  • also update the question with the expected output Commented May 6, 2022 at 16:17
  • Why not use an existing format like JSON and existing tools like jq? Commented May 6, 2022 at 16:38
  • @chepner because I am stuck with this format which is required by some other tool. Commented May 6, 2022 at 16:53
  • @markp-fuso items don't have spaces. I'm not sure what are embedded linefeeds? Commented May 6, 2022 at 16:53

5 Answers 5

2

perl:

perl -0777 -pE 's/.*unique_trigger\s*=\s*(.*)unique_end_trigger.*/$1/s; s/^\s+//gm' file.txt 
item1 item2 item3 ... itemN 
Sign up to request clarification or add additional context in comments.

Comments

1

One-liner

cat file.txt | tr -s "[:space:]" " " | \ sed -En "s/(.*)(unique_trigger = )(.*)(unique_end_trigger)/\3/p" | \ other_command 

1 Comment

Nice ides with squeezing the whitespace. An alternate take: tr -s '[:space:]' '\n' < file.txt | sed -En '/unique_trigger/,/unique_end_trigger/ {/^=|unique_(end_)?trigger$/!p;}'
1
 awk '/unique_end_trigger/&&--f||f||/unique_trigger/&&f++ {printf $1 " "}' <(sed 's/unique_trigger =/ & \n /' input_file) item1 item2 item3 ... itemN 

Comments

0

Not quite a one-liner, but it should do the trick as long as your triggers don't contain spaces.

flag=0 while read tr eq it ; do if [ "$tr" = "unique_trigger" ] ; then echo "$it" flag=1 elif [ $flag = 1 ] ; then if [ "$tr" = "unique_end_trigger" ] ; then flag=0 else echo "$tr" fi fi done 

Comments

0

Two solutions, using the same concept. When the start trigger is found, add the item (3rd item in the line) to a string. Until the end trigger is found, the item is the only work in the line, so add it to the string. Output the string at the end.

Bash parsing

#!/bin/bash file="file.txt" start_trigger="unique_trigger" end_trigger="unique_end_trigger" items='' between_trigger="no" while IFS= read -r line; do #echo "-----$line-----" # Start trigger lines if [[ "$line" =~ "$start_trigger =" ]] then items="$items $(echo "$line" | awk '{print $3}')" between_trigger="yes" continue fi # End trigger lines if [[ "$line" =~ "$end_trigger" ]] then between_trigger="no" continue fi # Lines between start and end trigger if [[ "$between_trigger" == "yes" ]] then items="$items $line" continue fi done < "$file" echo ">>$items<<" 

Using it: script.bash | xargs echo

Replace echo by any command.


Awk version

BEGIN { output = "" between = "no" } /unique_end_trigger/ { between = "no"; } /.*/ { if (between == "yes") output = output " " $1 } /unique_trigger/ { between = "yes"; output = output " " $3; } END { print output } 

Using it: awk -f script.awk file.txt | xargs echo

Replace echo with whatever command you want.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.