How to get the result of a grep command on a variable into another variable
I am listing through files within a directory that match a given criteria. One of the things I wish to do with each file in the directory is extract its 6 figure date and place that in a variable. My script currently looks like this:
for i in $(ls $INPUT_DIR | egrep -i '^'$INPUT_FILE_PREFIX'28([0]6|11)([0]9|[12]2|[3][01])'$INPUT_FILE_SUFFIX); do MYDATE=$("$i" | grep -oP '\d') echo $MYDATE done
The above leads to the error «somefile»: command not found . What seems strange to me is that if I replace MYDATE=$(«$i» | grep -oP ‘\d<6,6>‘) with echo «$i» | grep -oP ‘\d<6,6>‘ all works fine. How do I get my script to pass «$i» as a string rather than a command?6,6>
5 Answers 5
It looks like you are trying to parse out a six digit number in file names that start with $INPUT_FILE_PREFIX and ends with $INPUT_FILE_SUFFIX .
for name in "$INPUT_DIR/$INPUT_FILE_PREFIX". "$INPUT_FILE_SUFFIX"; do test -f "$name" || continue number=$ number=$ printf "Number = %s\n" "$number" done
Change every ? to 3 if you want to be sure to only match digits ( ? matches a single character regardless of what that character is).
The parameter substitutions in the loop removes the first part of the value of $name and then the last part of the remaining string, leaving the number (six characters between prefix and suffix) in the middle as the only thing left in the variable $number .
will, as you discovered, be interpreted as invoking whatever is in $i as a command. At the same time you said that putting echo in front of «$i» would make it work, which it does:
I have chosen this as the answer, as it is does address directly my particular query, though I appreciate others for pointing out other methods of looping through the files in the directory.
I would recommend a slightly different way of looping through the filenames — using bash’s extended globbing to gather the filenames:
shopt -s extglob for d in "$"/"$"93@(03|16)@(04|[12]3|3[01])"$" do [[ $d =~ $([[:digit:]]+)$ ]] MYDATE=$ done
The globbing syntax is nearly the same as the grep statement you had. Each set of @(. ) introduces a request to match any of the given patterns, which are separated by | . I noticed that the (presumed day) pattern of [3] was a single-character class, so I removed its surrounding brackets.
Once we have the filenames in the for loop, you can use bash’s conditional expression’s regular expression =~ operator to strip out the digits into MYDATE.
for i in $(ls $INPUT_DIR | egrep -i '^'$INPUT_FILE_PREFIX'26([0]9|12)([0]4|[12]9|[3][01])'$INPUT_FILE_SUFFIX);
In general, there’s no reason to use ls in a structure like this, it just makes the command more awkward to read, plus you run into issues with some corner cases (see ParsingLs in BashGuide). However, the regex you have can not be represented as a standard shell glob, so there’s some point into using it. Though since this was tagged with bash, we can do it in the shell, either with extglob (or using regex matches with the [[ .. ]] construct after a wider glob).
shopt -s extglob for i in "$INPUT_DIR/$INPUT_FILE_PREFIX"42@(06|12)@(08|[12]9|3[01])"$INPUT_FILE_SUFFIX" ; do
If you don’t really need such a strict pattern, you could just use 269382 instead.
In the assignment to MYDATE , I assume you just want to remove the prefix and the suffix. (though if your prefix/suffix contains a six-digit string, the grep would match that, too.)
MYDATE=$ # remove the directory MYDATE=$ # remove the prefix MYDATE=$ # and the suffix
shopt -s extglob for i in "$INPUT_DIR/$INPUT_FILE_PREFIX"15@(08|11)@(09|[12]9|3[01])"$INPUT_FILE_SUFFIX" ; do MYDATE=$ # remove the directory MYDATE=$ # remove the prefix MYDATE=$ # and the suffix echo "$MYDATE" done
passing grep into a variable in bash
I want to take out only the email address in this file by using bash script.So i put this script in my bash script named myscript:
#!/bin/bash file=$(myscript) var1=$(awk 'NR==2' $file) var2=$("$var1" | (grep -Eio '\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]\b')) echo $var2
But I failed to run this script.When I run this command manually in bash i can obtain the email address:
echo $var1 | grep -Eio '\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]\b'
I need to put the email address to store in a variable so i can use it in other function.Can someone show me how to solve this problem? Thanks.
@flesk yup..i’ve already done that.The $file have the exact line and content that i want to grep and it can echo without problem
In case the From: line is not on line 2: awk -F : ‘$1 == «From»
5 Answers 5
I think this is an overly complicated way to go about things, but if you just want to get your script to work, try this:
#!/bin/bash file="email.txt" var1=$(awk 'NR==2' $file) var2=$(echo "$var1" | grep -Eio '\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]\b') echo $var2
I’m not sure what file=$(myscript) was supposed to do, but on the next line you want a file name as argument to awk , so you should just assign email.txt as a string value to file , not execute a command called myscript . $var1 isn’t a command (it’s just a line from your text file), so you have to echo it to give grep anything useful to work with. The additional parentheses around grep are redundant.
BASH storing grep output into variable or array
I have two arrays: one is an array of CPU numbers and the other is an array of server names. What I’m doing is searching a file to spit out the server name with the CPU number on the same line. You can see the code below:
#!/bin/bash cpu=("Atom" "Q8200" "Q9300" "Q9550" "i5" "i7" "X3440" "E3 1230" "Dell 860" "Dell r410" "Dell R200" "E5645" "E5504" "Dell 1950" "Dell 2950 Dual QuadCore Xeon E5420") tknum=("tk676" "tk619" "tk20013" "tkc676" "tk74001") for i in "$" #being loop through tk numbers do temp=$(grep -i -m 1 "$i" /home/jeremysd/public_html/servers.txt) #return line tknumber is on and store in variable #echo "$temp" echo "$i" #Print out the tk number for j in "$" #begin loop through cpu numbers do echo "$temp" | grep -io "$j" #Return CPU number done done
sh array_test.sh tk676 Q9550 tk619 Dell R200 tk20013 dell R410 tkc676 Q9550
That shows the server name and then CPU under it. However, I want it to be comma separated so that I can import it into a database
Now, my thinking was to store the CPU type in a temporary variable and then echo it out, but doing so causes many blank lines to be entered into the string. The loop through the CPU type becomes:
for j in "$" #begin loop through cpu numbers do temp1=$(echo "$temp" | grep -io "$j") #Return CPU number echo $temp1 done
The results are below and show extra blank lines. Anybody have any idea on how to store the CPU variables in a string or array without all the extra spaces being added?
sh array_test.sh tk676 Q9550
Assign variable the grep value of command output
I have been recently introduced to the world of bash scripting. I currently have a video of file which I want to grep the duration. The problem is assigning the duration value to a variable. I get the errors shown below. What is the best way to assign duration value to a variable? Also is it necessary to have two greps. For example the first grep gives duration=171.805000 , Then i have to do a second grep for the decimal value only. snippet
#!/bin/bash/ str_duration=echo$(ffprobe -i "media/myvideo.mp4" -show_format -v quiet | grep duration) int_duration=echo $ | grep -o ' 1\+\.4\+'
line 15: echoduration=171.805000: command not found
ffprobe version git-2014-12-27-d4fd3f2 Copyright (c) 2007-2014 the FFmpeg developers built on Dec 27 2014 12:23:47 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1) configuration: --enable-gpl --enable-libfaac --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-librtmp --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-nonfree --enable-version3 libavutil 54. 15.100 / 54. 15.100 libavcodec 56. 19.100 / 56. 19.100 libavformat 56. 16.102 / 56. 16.102 libavdevice 56. 3.100 / 56. 3.100 libavfilter 5. 6.100 / 5. 6.100 libswscale 3. 1.101 / 3. 1.101 libswresample 1. 1.100 / 1. 1.100 libpostproc 53. 3.100 / 53. 3.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/media/myvideo.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf56.16.102 Duration: 00:02:51.81, start: 0.000333, bitrate: 1504 kb/s Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1367 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default) Metadata: handler_name : VideoHandler Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 127 kb/s (default) Metadata: handler_name : SoundHandler duration=171.805000