Grep command not giving expected output - bash

I am running the below line in a shell script
echo "$(tr -s '\n' ' ' < ${data[1]} | grep -oP '<af:popup.*?"${data[2]}".*?>')"
echo "(tr -s '\n' ' ' < ${data[1]} | grep -oP '<af:popup.*?"${data[2]}".*?>')"
The command is supposed to translate all \n from file ${data[1]} and inside this file a pattern something like this:
(af:popup.*?logicalCostingRecordExistsPopup.*?)
Issue is the first line is returning null data. Just to validate my script, I echoed the command to check what is getting replaced and run in directly in a shell.Output came as below
tr -s '\n' ' ' < hello.jsff | grep -oP '<af:popup.*? logicalCostingRecordExistsPopup.*?>'
When I run it directly in shell, it gives me expected output.
Don't know why it is not giving output when running inside in shell script

Instead of using double quotes, use single quotes.
echo "$(tr -s '\n' ' ' < ${data[1]} | grep -oP '<af:popup.*?'${data[2]}.*?>')"

Related

How to remove all spaces from command output

I'm writing a bash script for ssh key need to compare from local to remote. I have the command to check the key but command output result shows line by line. I need to get the output without spaces is there anyway to get output which is I'm expecting.
$ cat ex.txt
this is an example
this is line 2
$ cat ex.txt |tr -d ' '
thisisanexample
thisisline2
$ cat ex.txt |tr -d '\n'
this is an example this is line 2
$ cat ex.txt |tr -d '\n'' '
thisisanexamplethisisline2
tr = translate or delete characters
-d = delete character / characters
'\n' = newlines
' ' = spaces

Creating a bash alias that ends in single quotation

I have a command line string:
ls | sed -e 's/^/"/g' -e 's/$/"/g' | tr '\n' ' '
which outputs file names in the current folder, in a single line, surrounded by quotations.
I attempted to add this to my .bash_profile as an alias, however I think the single quotes are causing an issue and I can't get it to work.
I tried this with no luck:
alias='ls | sed -e 's/^/"/g' -e 's/$/"/g' | tr '\n' ' ''
How would one go about creating an alias for the above?
Thanks in advance to anyone who can help with this noob question and I appreciate your time :)
Cheers,
Stephen.
Enquote the whole command in double quotes and escape the double quotes inside the command with a backslash:
alias a="ls | sed -e 's/^/\"/g' -e 's/$/\"/g' | tr '\n' ' '"
or use a function
a() {
ls | sed -e 's/^/"/g' -e 's/$/"/g' | tr '\n' ' '
}
By the way: Parsing ls is a bad practice. It would be safer and easier to use globs and printf:
printf '"%s" ' *
or, if you want to properly quote for using the arguments inside eval or something similar
printf '%q ' *
work here with using \"
alias X="ls | sed -e 's/^/\"/g' -e 's/$/\"/g' | tr '\n' ' '"
The alias should enclose the command line into ' AND each already existing ' should be escaped with '\''
Give a try to this:
alias lsquoted='ls | sed -e '\''s/^/"/g'\'' -e '\''s/$/"/g'\'' | tr '\''\n'\'' '\'' '\'''

Linux command echo files names until char

Here is my code
cd /bin/
echo *xyz?2* | cut -f 1 -d '.'
Please, how can i change this command to display files without extension ?
Bests.
Dump the filenames into an array and then use parameter expansion:
$ arr=(xyz?2*); echo "${arr[*]%.*}"
xyz32281 xyz32406 xyz32459 xyz3252 xyz7214 xyz8286
Assuming your filenames don't have any whitespace or glob characters.
You can just use printf '%s\n' instead of echo in your command:
printf '%s\n' *xyz?2* | cut -f 1 -d '.'
xyz32281
xyz32406
xyz32459
xyz3252
xyz7214
xyz8286
If you must use echo then use awk as this:
echo *xyz?2* | awk '{for(i=1; i<=NF; i++) print (split($i, a, /\./)==2 ? a[1] : $i)}'
xyz32281
xyz32406
xyz32459
xyz3252
xyz7214
xyz8286
This awk command iterated through each filename matched by glob pattern and splits each name by dot. If dot is found then first part is printed otherwise full filename is printed.
Your problem is that all files of echo *xyz?2* are shown in one line. When the filenames are without spaces/newlines, you can fix this by moving them to different lines and joining theem again when finished.
echo *xyz?2* | tr ' ' '\n' | cut -f 1 -d '.' | tr '\n' ' '| sed '$s/ $/\n/'
You can do this a lot easier with sed:
echo *xyz?2* | sed 's/[.][^. ]*//g'

Pass multiple file names captured in a variable to a command (vim)

I am trying to create a script that opens automatically any files containing a particular pattern.
This is what I achieved so far:
xargs -d " " vim < "$(grep --color -r test * | cut -d ':' -f 1 | uniq | sed ':a;N;$!ba;s/\n/ /g')"
The problem is that vim does not recognize the command as separate file of list, but as a whole filename instead:
zsh: file name too long: ..............
Is there an easy way to achieve it? What am I missing?
The usual way to call xargs is just to pass the arguments with newlines via a pipe:
grep -Rl test * | xargs vim
Note that I'm also passing the -l argument to grep to list the files that contain my pattern.
Use this:
vim -- `grep -rIl test *`
-I skip matching in binary files
-l print file name at first match
Try to omit xargs, becouse this leads to incorrect behaviour of vim:
Vim: Warning: Input is not from a terminal
What I usually do is append the following line to a list of files:
> ~/.files.txt && vim $(cat ~/.files.txt | tr "\n" " ")
For example :
grep --color -r test * > ~/.files.txt && vim $(cat ~/.files.txt | tr "\n" " ")
I have the following in my .bashrc to bind VV (twice V in uppercase) to insert that automatically :
insertinreadline() {
READLINE_LINE=${READLINE_LINE:0:$READLINE_POINT}$1${READLINE_LINE:$READLINE_POINT}
READLINE_POINT=`expr $READLINE_POINT + ${#1}`
}
bind -x '"VV": insertinreadline " > ~/.files.txt && vim \$(cat ~/.files.txt | tr \"\\n\" \" \")"'

running bash pipe commands in background with & ampersand

time for i in `ls /tmp/chunk*`; do (cat $i | tr ' ' '\n' | sort | uniq > /tmp/line${i:10}) & ;done
bash: syntax error near unexpected token `;'
Whats the syntax error in the above command? I also tried using {} and ended the piped commands with ;. But same error shows up ...
You should put the & inside the (), if you want to run all the jobs in parallel in the background.
time for i in `ls /tmp/chunk*`; do
(cat $i | tr ' ' '\n' | sort | uniq > /tmp/line${i:10} &)
done
You can include the & in braces:
time for i in `ls /tmp/chunk*`; do
{(cat $i | tr ' ' '\n' | sort | uniq > /tmp/line${i:10}) &};
done
& is a separator and so is redundant with ;
I.E. remove the final ;
for i in /tmp/chunk*; do tr ' ' '\n' <$i | sort -u > /tmp/line${i:10}& done

Resources